diff --git a/.env.production b/.env.production index 381c7264..09bb27d3 100644 --- a/.env.production +++ b/.env.production @@ -1,4 +1,4 @@ -NEXT_PUBLIC_API_SERVER_PATH="http://1.248.227.176:38080" +NEXT_PUBLIC_API_SERVER_PATH="https://api.hanasys.jp/" NEXT_PUBLIC_HOST_URL="http://1.248.227.176:4000" @@ -7,5 +7,7 @@ SESSION_SECRET="i3iHH1yp2/2SpQSIySQ4bpyc4g0D+zCF9FAn5xUG0+Y=" # NEXT_PUBLIC_CONVERTER_API_URL="https://v2.convertapi.com/convert/dwg/to/png?Secret=secret_bV5zuYMyyIYFlOb3" NEXT_PUBLIC_CONVERTER_API_URL="https://v2.convertapi.com/convert/dwg/to/png?Secret=secret_yAS4QDalL9jgQ7vS" -NEXT_PUBLIC_Q_ORDER_AUTO_LOGIN_URL="https://q-order.q-cells.jp/eos/login/autoLogin" -NEXT_PUBLIC_Q_MUSUBI_AUTO_LOGIN_URL="https://q-musubi.q-cells.jp/qm/login/autoLogin" \ No newline at end of file +# NEXT_PUBLIC_Q_ORDER_AUTO_LOGIN_URL="https://q-order.q-cells.jp/eos/login/autoLogin" +# NEXT_PUBLIC_Q_MUSUBI_AUTO_LOGIN_URL="https://q-musubi.q-cells.jp/qm/login/autoLogin" +NEXT_PUBLIC_Q_ORDER_AUTO_LOGIN_URL="http://q-order-stg.q-cells.jp:8120/eos/login/autoLogin" +NEXT_PUBLIC_Q_MUSUBI_AUTO_LOGIN_URL="http://q-musubi-stg.q-cells.jp:8120/qm/login/autoLogin" \ No newline at end of file diff --git a/docs/2025-02-13_Qcell_회의.txt b/docs/2025-02-13_Qcell_회의.txt new file mode 100644 index 00000000..3aa60619 --- /dev/null +++ b/docs/2025-02-13_Qcell_회의.txt @@ -0,0 +1,36 @@ +1. 회로할당 -> + 수동 할당시 와트수 소수점 노출 + +2. 모듈 -> + 멀티 모듈일시 모듈 순번에 따라 배치면 그리기 적용해야됨 + 멀티 모듈시 모듈 간격 붙여서 조정 + +3. contextMenu -> + 한번 클릭 후 contextMenu 호출 재호출시 화면에 안나옴 + +4. 수치 입력시 -> + 반각?전각? 입력 처리 필요???????????????? + +5. 지도 호출 -> + 최초 호출 후 삭제, 재호출 안됨 + +6. 도면 화면 -> + redo, undo 제거 + +7. 모든 배치면 -> + 배치면 외각선 굵기 조절 + +8. 패브릭 캔버스 -> + 줌, 확대 기능 선택 오류 수정 필요 + +9. 모듈선택 -> + 모듈 선택 페이지 단계 변경 예정정(현업 화면에 너무 크게 적용) + +10. 외벽선 삭제시 수치 삭제 처리 필요 + +11. 모듈 삭제 후 재 설치시 모듈이 겹친다고 오류남 + +12. 모듈 수동시 첫번째는 아무데나 놓을 수 있고 두번째 부터는 무조건 주변에 모듈이 있어야 한다는 조건이 있어야 한다고 함 + +13. 견적서 다운로드 이미지 정비율이 아님 + diff --git a/docs/2025-02-14_Qcell_회의.txt b/docs/2025-02-14_Qcell_회의.txt new file mode 100644 index 00000000..5add84f4 --- /dev/null +++ b/docs/2025-02-14_Qcell_회의.txt @@ -0,0 +1,10 @@ +1. 오픈 예정일정 -> 신상품 7월에 오픈 그와 같이 하는게 어떻냐? + +2. 웹 상에서 단축키 모드 추가 + +3. 형이동 동선이동 작업 해보겠다. + +4. 모듈 작업 확정 (좌하, 우상) + +5. 발전 시뮬레이션 qsp에 이관 작업(유지보수) + diff --git a/MainLayout.codediagram b/docs/diagrams/MainLayout.codediagram similarity index 100% rename from MainLayout.codediagram rename to docs/diagrams/MainLayout.codediagram diff --git a/docs/diagrams/canvas-setting.codediagram b/docs/diagrams/canvas-setting.codediagram new file mode 100644 index 00000000..bd87ebb4 --- /dev/null +++ b/docs/diagrams/canvas-setting.codediagram @@ -0,0 +1 @@ +{"id":-1,"name":"Onboarding diagram","userId":-1,"createdAt":"","updatedAt":"","content":{"items":[{"uid":"HduNR37Az-","position":{"x":800,"y":-590},"sizes":{"width":400,"height":146},"autoheight":true,"blockContent":{"type":"doc","content":[{"type":"heading","attrs":{"level":1},"content":[{"type":"text","text":"\bCanvas Setting "},{"type":"text","marks":[{"type":"bold"}],"text":"☀️"}]},{"type":"bulletList","content":[{"type":"listItem","content":[{"type":"paragraph","content":[{"type":"text","text":"canvas 전체 내용을 설정한다."}]}]},{"type":"listItem","content":[{"type":"paragraph","content":[{"type":"text","text":"저장 버튼 없이 UI를 변경하면 Update가 일어난다."}]}]}]}]},"color":{"bgColor":"hsla(211, 33%, 22%, 1)","bgName":"blue"},"nodeType":"block"},{"uid":"DiKZ2umB3G","position":{"x":450,"y":-250},"sizes":{"width":549.78125,"height":189.5},"autoheight":true,"blockContent":{"content":[{"type":"filePathNode","attrs":{"pathToFile":"src/components/floor-plan/modal/setting01/","version":1},"content":[{"type":"text","marks":[{"type":"bold"}],"text":"SettingModal01.jsx"}]},{"type":"codeBlock","attrs":{"language":"javascript","wrapCode":true},"content":[{"type":"text","text":"{buttonAct === 1 && }\n{buttonAct === 2 && }\n{buttonAct === 3 && }"}]}]},"nodeType":"block"},{"uid":"EAKK_XFrUP","position":{"x":70,"y":90},"sizes":{"width":400,"height":210},"autoheight":false,"blockContent":{"type":"doc","content":[{"type":"filePathNode","attrs":{"pathToFile":"src/components/floor-plan/modal/setting01/","version":1},"content":[{"type":"text","marks":[{"type":"bold"}],"text":"FirstOption.jsx"}]},{"type":"paragraph","content":[{"type":"text","marks":[{"type":"bold"}],"text":"디스플레이 설정"}]},{"type":"codeBlock","attrs":{"language":"javascript","wrapCode":true},"content":[{"type":"text","text":"export default function FirstOption(props) {"}]}]},"nodeType":"block"},{"uid":"-QZuVi6n7M","position":{"x":540,"y":90},"sizes":{"width":400,"height":182.5},"autoheight":true,"blockContent":{"type":"doc","content":[{"type":"filePathNode","attrs":{"pathToFile":"src/components/floor-plan/modal/setting01/","version":1},"content":[{"type":"text","marks":[{"type":"bold"}],"text":"SecondOption.jsx"}]},{"type":"paragraph","content":[{"type":"text","marks":[{"type":"bold"}],"text":"글꼴 및 도면 크기 설정"}]},{"type":"codeBlock","attrs":{"language":"javascript","wrapCode":true},"content":[{"type":"text","text":"export default function SecondOption(props) {"}]}]},"nodeType":"block"},{"uid":"OIDIoPPwFU","position":{"x":1220,"y":90},"sizes":{"width":400,"height":182.5},"autoheight":true,"blockContent":{"type":"doc","content":[{"type":"filePathNode","attrs":{"pathToFile":"src/components/floor-plan/modal/setting01/","version":1},"content":[{"type":"text","marks":[{"type":"bold"}],"text":"GridOption.jsx"}]},{"type":"paragraph","content":[{"type":"text","marks":[{"type":"bold"}],"text":"그리드 설정"}]},{"type":"codeBlock","attrs":{"language":"javascript","wrapCode":true},"content":[{"type":"text","text":"export default function GridOption(props) {"}]}]},"nodeType":"block"},{"uid":"iEbZe6FrdP","position":{"x":550,"y":380},"sizes":{"width":400,"height":200},"autoheight":true,"blockContent":{"type":"doc","content":[{"type":"filePathNode","attrs":{"pathToFile":"src/components/floor-plan/modal/dimensionLine/","version":1},"content":[{"type":"text","marks":[{"type":"bold"}],"text":"DimensionLineSetting.jsx"}]},{"type":"paragraph","content":[{"type":"text","marks":[{"type":"bold"}],"text":"글꼴 및 크기 변경"}]},{"type":"codeBlock","attrs":{"language":"javascript","wrapCode":true},"content":[{"type":"text","text":"export default function DimensionLineSetting(props) {"}]}]},"nodeType":"block"},{"uid":"5ovY6Y7atI","position":{"x":1010,"y":380},"sizes":{"width":400,"height":182.5},"autoheight":true,"blockContent":{"type":"doc","content":[{"type":"filePathNode","attrs":{"pathToFile":"src/components/floor-plan/modal/grid/","version":1},"content":[{"type":"text","marks":[{"type":"bold"}],"text":"DotLineGrid.jsx"}]},{"type":"paragraph","content":[{"type":"text","marks":[{"type":"bold"}],"text":"점, 선, 그리드 설정"}]},{"type":"codeBlock","attrs":{"language":"javascript","wrapCode":true},"content":[{"type":"text","text":"export default function DotLineGrid(props) {"}]}]},"nodeType":"block"},{"uid":"yVBft0fd68","position":{"x":1470,"y":380},"sizes":{"width":400,"height":200},"autoheight":true,"blockContent":{"type":"doc","content":[{"type":"filePathNode","attrs":{"pathToFile":"src/components/common/color-picker/","version":1},"content":[{"type":"text","marks":[{"type":"bold"}],"text":"ColorPickerModal.jsx"}]},{"type":"paragraph","content":[{"type":"text","marks":[{"type":"bold"}],"text":"색 설정"}]},{"type":"codeBlock","attrs":{"language":"javascript","wrapCode":true},"content":[{"type":"text","text":"export default function ColorPickerModal(props) {"}]}]},"nodeType":"block"},{"uid":"KcDc1JqWZL","position":{"x":270,"y":-700},"sizes":{"width":470,"height":336.5},"autoheight":true,"blockContent":{"type":"doc","content":[{"type":"filePathNode","attrs":{"pathToFile":"src/components/floor-plan/","version":1},"content":[{"type":"text","marks":[{"type":"bold"}],"text":"CanvasMenu.jsx"}]},{"type":"paragraph","content":[{"type":"text","marks":[{"type":"bold"}],"text":"modal 창 ON"}]},{"type":"codeBlock","attrs":{"language":"javascript","wrapCode":true},"content":[{"type":"text","text":"const handlePopup = () => {\n const id = uuidv4()\n addPopup(id, 1, , true)\n}"}]},{"type":"paragraph","content":[{"type":"text","text":"canvas 설정 조회"}]},{"type":"codeBlock","attrs":{"language":"javascriptreact","wrapCode":false},"content":[{"type":"text","text":"const { fetchSettings } = useCanvasSetting()"}]}]},"nodeType":"block"},{"uid":"y2Vg-dWtlJ","position":{"x":-390,"y":-620},"sizes":{"width":520,"height":385.5},"autoheight":true,"blockContent":{"type":"doc","content":[{"type":"filePathNode","attrs":{"pathToFile":"src/hooks/option/","version":1},"content":[{"type":"text","marks":[{"type":"bold"}],"text":"useCanvasSetting.js"}]},{"type":"paragraph","content":[{"type":"text","marks":[{"type":"bold"}],"text":"canvas 설정 관리 hook"}]},{"type":"codeBlock","attrs":{"language":"javascript","wrapCode":true},"content":[{"type":"text","text":"const fetchSettings = async () => {"}]},{"type":"codeBlock","attrs":{"language":"javascript","wrapCode":false},"content":[{"type":"text","text":"const [settingsData, setSettingsData] = useState({\n ...settingModalFirstOptions,\n ...settingModalSecondOptions,\n ...globalFont,\n ...dotLineGridSetting,\n ...planSizeSettingMode,\n ...dimensionLineSettings,\n ...color,\n })"}]}]},"nodeType":"block"}],"configs":{"centerX":373.0590486994188,"centerY":572.9825354968084,"zoomLevel":1.017264811197917},"arrowData":{"arrowsMap":{"arrow-point-bI0wBh3Ufk-bottom-point-PSPLIYKa9J-top":{"to":"point-PSPLIYKa9J-top","from":"point-bI0wBh3Ufk-bottom","label":"Normal Box","direction":"ft","selectable":true},"arrow-point-bI0wBh3Ufk-bottom-point-ytXK_ayIc1-top":{"to":"point-ytXK_ayIc1-top","from":"point-bI0wBh3Ufk-bottom","label":"Code Box","direction":"ft","selectable":true},"arrow-point-hyyRZE3E8u-right-point-6ZopTaEaDZ-left":{"to":"point-6ZopTaEaDZ-left","from":"point-hyyRZE3E8u-right","label":"call","direction":"ft","selectable":true}},"pointsMap":{"point-PSPLIYKa9J-top":{"x":805.9999797489683,"y":60,"id":"point-PSPLIYKa9J-top","direction":"top"},"point-ytXK_ayIc1-top":{"x":205.99999493724206,"y":60,"id":"point-ytXK_ayIc1-top","direction":"top"},"point-6ZopTaEaDZ-left":{"x":220,"y":605.9999898744841,"id":"point-6ZopTaEaDZ-left","direction":"left"},"point-hyyRZE3E8u-right":{"x":100,"y":606,"id":"point-hyyRZE3E8u-right","direction":"right"},"point-bI0wBh3Ufk-bottom":{"x":515.9999797489683,"y":-40,"id":"point-bI0wBh3Ufk-bottom","direction":"bottom"}},"edgesMap":{"edge-DiKZ2umB3G-DiKZ2umB3G-bottom-EAKK_XFrUP-EAKK_XFrUP-top":{"uid":"edge-DiKZ2umB3G-DiKZ2umB3G-bottom-EAKK_XFrUP-EAKK_XFrUP-top","fromNodeId":"DiKZ2umB3G","fromHandleId":"DiKZ2umB3G-bottom","toNodeId":"EAKK_XFrUP","toHandleId":"EAKK_XFrUP-top","direction":"ft","selectable":true,"type":"solid","content":{"label":""}},"edge-DiKZ2umB3G-DiKZ2umB3G-bottom--QZuVi6n7M--QZuVi6n7M-top":{"uid":"edge-DiKZ2umB3G-DiKZ2umB3G-bottom--QZuVi6n7M--QZuVi6n7M-top","fromNodeId":"DiKZ2umB3G","fromHandleId":"DiKZ2umB3G-bottom","toNodeId":"-QZuVi6n7M","toHandleId":"-QZuVi6n7M-top","direction":"ft","selectable":true,"type":"solid","content":{"label":""}},"edge-DiKZ2umB3G-DiKZ2umB3G-bottom-OIDIoPPwFU-OIDIoPPwFU-top":{"uid":"edge-DiKZ2umB3G-DiKZ2umB3G-bottom-OIDIoPPwFU-OIDIoPPwFU-top","fromNodeId":"DiKZ2umB3G","fromHandleId":"DiKZ2umB3G-bottom","toNodeId":"OIDIoPPwFU","toHandleId":"OIDIoPPwFU-top","direction":"ft","selectable":true,"type":"solid","content":{"label":""}},"edge--QZuVi6n7M--QZuVi6n7M-bottom-iEbZe6FrdP-iEbZe6FrdP-top":{"uid":"edge--QZuVi6n7M--QZuVi6n7M-bottom-iEbZe6FrdP-iEbZe6FrdP-top","fromNodeId":"-QZuVi6n7M","fromHandleId":"-QZuVi6n7M-bottom","toNodeId":"iEbZe6FrdP","toHandleId":"iEbZe6FrdP-top","direction":"ft","selectable":true,"type":"solid","content":{"label":""}},"edge-OIDIoPPwFU-OIDIoPPwFU-bottom-5ovY6Y7atI-5ovY6Y7atI-top":{"uid":"edge-OIDIoPPwFU-OIDIoPPwFU-bottom-5ovY6Y7atI-5ovY6Y7atI-top","fromNodeId":"OIDIoPPwFU","fromHandleId":"OIDIoPPwFU-bottom","toNodeId":"5ovY6Y7atI","toHandleId":"5ovY6Y7atI-top","direction":"ft","selectable":true,"type":"solid","content":{"label":""}},"edge-OIDIoPPwFU-OIDIoPPwFU-bottom-yVBft0fd68-yVBft0fd68-top":{"uid":"edge-OIDIoPPwFU-OIDIoPPwFU-bottom-yVBft0fd68-yVBft0fd68-top","fromNodeId":"OIDIoPPwFU","fromHandleId":"OIDIoPPwFU-bottom","toNodeId":"yVBft0fd68","toHandleId":"yVBft0fd68-top","direction":"ft","selectable":true,"type":"solid","content":{"label":""}},"edge-KcDc1JqWZL-KcDc1JqWZL-bottom-DiKZ2umB3G-DiKZ2umB3G-top":{"uid":"edge-KcDc1JqWZL-KcDc1JqWZL-bottom-DiKZ2umB3G-DiKZ2umB3G-top","fromNodeId":"KcDc1JqWZL","fromHandleId":"KcDc1JqWZL-bottom","toNodeId":"DiKZ2umB3G","toHandleId":"DiKZ2umB3G-top","direction":"ft","selectable":true,"type":"solid","content":{"label":""}},"edge-KcDc1JqWZL-KcDc1JqWZL-left-y2Vg-dWtlJ-y2Vg-dWtlJ-right":{"uid":"edge-KcDc1JqWZL-KcDc1JqWZL-left-y2Vg-dWtlJ-y2Vg-dWtlJ-right","fromNodeId":"KcDc1JqWZL","fromHandleId":"KcDc1JqWZL-left","toNodeId":"y2Vg-dWtlJ","toHandleId":"y2Vg-dWtlJ-right","direction":"ft","selectable":true,"type":"solid","content":{"label":""}}}}}} \ No newline at end of file diff --git a/docs/diagrams/배치면초기설정.codediagram b/docs/diagrams/배치면초기설정.codediagram new file mode 100644 index 00000000..814a256d --- /dev/null +++ b/docs/diagrams/배치면초기설정.codediagram @@ -0,0 +1 @@ +{"id":-1,"name":"Onboarding diagram","userId":-1,"createdAt":"","updatedAt":"","content":{"items":[{"uid":"HduNR37Az-","position":{"x":690,"y":-270},"sizes":{"width":400,"height":168},"autoheight":true,"blockContent":{"type":"doc","content":[{"type":"heading","attrs":{"level":1},"content":[{"type":"text","text":"배치면 초기설정 "},{"type":"text","marks":[{"type":"bold"}],"text":"☀️"}]},{"type":"bulletList","content":[{"type":"listItem","content":[{"type":"paragraph","content":[{"type":"text","text":"플랜당 필수 설정"}]}]},{"type":"listItem","content":[{"type":"paragraph","content":[{"type":"text","text":"필수로 설정이 저장되어야 하기 때문에 닫기 버튼 없음"}]}]},{"type":"listItem","content":[{"type":"paragraph","content":[{"type":"text","text":"저장 버튼으로 update 처리"}]}]}]}]},"color":{"bgColor":"hsla(211, 33%, 22%, 1)","bgName":"blue"},"nodeType":"block"},{"uid":"eB4rr9xOVw","position":{"x":500,"y":-40},"sizes":{"width":810,"height":182.5},"autoheight":true,"blockContent":{"type":"doc","content":[{"type":"filePathNode","attrs":{"pathToFile":"src/components/floor-plan/modal/placementShape/","version":1},"content":[{"type":"text","marks":[{"type":"bold"}],"text":"PlacementShapeSetting.jsx"}]},{"type":"paragraph","content":[{"type":"text","marks":[{"type":"bold"}],"text":"배치면 초기 설정 팝업"}]},{"type":"codeBlock","attrs":{"language":"javascript","wrapCode":true},"content":[{"type":"text","text":"export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, planNo, openPoint }) {"}]}]},"nodeType":"block"},{"uid":"dzN8hw1chO","position":{"x":990,"y":310},"sizes":{"width":550,"height":361},"autoheight":true,"blockContent":{"type":"doc","content":[{"type":"filePathNode","attrs":{"pathToFile":"src/hooks/option/","version":1},"content":[{"type":"text","marks":[{"type":"bold"}],"text":"useCanvasSetting.js"}]},{"type":"codeBlock","attrs":{"language":"javascript","wrapCode":true},"content":[{"type":"text","text":"/**\n * 기본설정(PlacementShapeSetting) 조회 및 초기화\n */\nconst fetchBasicSettings = async (planNo, openPoint) => {"}]},{"type":"paragraph"},{"type":"codeBlock","attrs":{"language":"javascript","wrapCode":false},"content":[{"type":"text","text":"/**\n * 기본설정(PlacementShapeSetting) 저장\n */\nconst basicSettingSave = async (params) => {"}]}]},"nodeType":"block"},{"uid":"YX7IHZIiqg","position":{"x":330,"y":310},"sizes":{"width":590,"height":259.5},"autoheight":true,"blockContent":{"content":[{"type":"filePathNode","attrs":{"pathToFile":"src/hooks/","version":1},"content":[{"type":"text","marks":[{"type":"bold"}],"text":"usePlan.js"}]},{"type":"codeBlock","attrs":{"language":"javascript","wrapCode":true},"content":[{"type":"text","text":"/**\n * 플랜 삭제 시 배치면 초기설정 데이터 삭제\n *\n * @param {string} objectNo - 물건번호\n * @param {string} planNo - 플랜번호\n */\nconst deleteBasicSettings = async (objectNo, planNo) => {"}]}]},"nodeType":"block"}],"configs":{"centerX":47.05904869941878,"centerY":349.9825354968084,"zoomLevel":1.017264811197917},"arrowData":{"arrowsMap":{"arrow-point-bI0wBh3Ufk-bottom-point-PSPLIYKa9J-top":{"to":"point-PSPLIYKa9J-top","from":"point-bI0wBh3Ufk-bottom","label":"Normal Box","direction":"ft","selectable":true},"arrow-point-bI0wBh3Ufk-bottom-point-ytXK_ayIc1-top":{"to":"point-ytXK_ayIc1-top","from":"point-bI0wBh3Ufk-bottom","label":"Code Box","direction":"ft","selectable":true},"arrow-point-hyyRZE3E8u-right-point-6ZopTaEaDZ-left":{"to":"point-6ZopTaEaDZ-left","from":"point-hyyRZE3E8u-right","label":"call","direction":"ft","selectable":true}},"pointsMap":{"point-PSPLIYKa9J-top":{"x":805.9999797489683,"y":60,"id":"point-PSPLIYKa9J-top","direction":"top"},"point-ytXK_ayIc1-top":{"x":205.99999493724206,"y":60,"id":"point-ytXK_ayIc1-top","direction":"top"},"point-6ZopTaEaDZ-left":{"x":220,"y":605.9999898744841,"id":"point-6ZopTaEaDZ-left","direction":"left"},"point-hyyRZE3E8u-right":{"x":100,"y":606,"id":"point-hyyRZE3E8u-right","direction":"right"},"point-bI0wBh3Ufk-bottom":{"x":515.9999797489683,"y":-40,"id":"point-bI0wBh3Ufk-bottom","direction":"bottom"}},"edgesMap":{"edge-eB4rr9xOVw-eB4rr9xOVw-bottom-YX7IHZIiqg-YX7IHZIiqg-top":{"uid":"edge-eB4rr9xOVw-eB4rr9xOVw-bottom-YX7IHZIiqg-YX7IHZIiqg-top","fromNodeId":"eB4rr9xOVw","fromHandleId":"eB4rr9xOVw-bottom","toNodeId":"YX7IHZIiqg","toHandleId":"YX7IHZIiqg-top","direction":"ft","selectable":true,"type":"solid","content":{"label":""}},"edge-eB4rr9xOVw-eB4rr9xOVw-bottom-dzN8hw1chO-dzN8hw1chO-top":{"uid":"edge-eB4rr9xOVw-eB4rr9xOVw-bottom-dzN8hw1chO-dzN8hw1chO-top","fromNodeId":"eB4rr9xOVw","fromHandleId":"eB4rr9xOVw-bottom","toNodeId":"dzN8hw1chO","toHandleId":"dzN8hw1chO-top","direction":"ft","selectable":true,"type":"solid","content":{"label":""}}}}}} \ No newline at end of file diff --git a/next.config.mjs b/next.config.mjs index d4759fb3..c940dbf8 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -15,6 +15,13 @@ const nextConfig = { sassOptions: { includePaths: ['./src/styles'], }, + experimental: { + staleTimes: { + dynamic: 0, + dynamicSWR: 0, + dynamicSSR: 0, + }, + }, } export default nextConfig diff --git a/package.json b/package.json index c2b9e6cf..bf52888e 100644 --- a/package.json +++ b/package.json @@ -5,12 +5,12 @@ "scripts": { "dev": "next dev", "build": "next build", - "start": "next start", + "start": "next start -p 3000", + "start:dev": "next start -p 3001", "lint": "next lint", "serve": "node server.js" }, "dependencies": { - "@nextui-org/react": "^2.4.2", "ag-grid-react": "^32.0.2", "axios": "^1.7.8", "big.js": "^6.2.2", @@ -37,6 +37,8 @@ "react-responsive-modal": "^6.4.2", "react-select": "^5.8.1", "recoil": "^0.7.7", + "sqlite": "^5.1.1", + "sqlite3": "^5.1.7", "sweetalert2": "^11.14.1", "sweetalert2-react-content": "^5.0.7", "swr": "^2.3.0", diff --git a/public/static/images/canvas/object_img01.svg b/public/static/images/canvas/object_img01.svg index 1d72f00b..0f5615a6 100644 --- a/public/static/images/canvas/object_img01.svg +++ b/public/static/images/canvas/object_img01.svg @@ -1,16 +1,14 @@ - - + + + + + - - - - - - + diff --git a/public/static/images/canvas/object_img02.svg b/public/static/images/canvas/object_img02.svg index ab1e8f43..85f47edf 100644 --- a/public/static/images/canvas/object_img02.svg +++ b/public/static/images/canvas/object_img02.svg @@ -1,21 +1,22 @@ - - + + + + + - + - - - - - + + + - + diff --git a/public/static/images/canvas/shape/180deg/plane_tab01.svg b/public/static/images/canvas/shape/180deg/plane_tab01.svg index 84c22986..7669a51b 100644 --- a/public/static/images/canvas/shape/180deg/plane_tab01.svg +++ b/public/static/images/canvas/shape/180deg/plane_tab01.svg @@ -1,12 +1,16 @@ - - - - - - - - - - - + + + + + + + + + + + + + + + diff --git a/public/static/images/canvas/shape/270deg/plane_tab01.svg b/public/static/images/canvas/shape/270deg/plane_tab01.svg index 22b32884..3fd9d7e7 100644 --- a/public/static/images/canvas/shape/270deg/plane_tab01.svg +++ b/public/static/images/canvas/shape/270deg/plane_tab01.svg @@ -1,12 +1,16 @@ - - - - - - - - - - - + + + + + + + + + + + + + + + diff --git a/public/static/images/canvas/shape/90deg/plane_tab01.svg b/public/static/images/canvas/shape/90deg/plane_tab01.svg index 46476194..c41f7dee 100644 --- a/public/static/images/canvas/shape/90deg/plane_tab01.svg +++ b/public/static/images/canvas/shape/90deg/plane_tab01.svg @@ -1,12 +1,16 @@ - - - - - - - - - - - + + + + + + + + + + + + + + + diff --git a/public/static/images/canvas/shape/normal/plane_tab01.svg b/public/static/images/canvas/shape/normal/plane_tab01.svg index 121b7025..1091f744 100644 --- a/public/static/images/canvas/shape/normal/plane_tab01.svg +++ b/public/static/images/canvas/shape/normal/plane_tab01.svg @@ -1,12 +1,16 @@ - - - - - - - - - - - + + + + + + + + + + + + + + + diff --git a/public/static/images/canvas/shape/re_180deg/plane_tab01.svg b/public/static/images/canvas/shape/re_180deg/plane_tab01.svg index aab78f30..60521209 100644 --- a/public/static/images/canvas/shape/re_180deg/plane_tab01.svg +++ b/public/static/images/canvas/shape/re_180deg/plane_tab01.svg @@ -1,12 +1,16 @@ - - - - - - - - - - - + + + + + + + + + + + + + + + diff --git a/public/static/images/canvas/shape/re_270deg/plane_tab01.svg b/public/static/images/canvas/shape/re_270deg/plane_tab01.svg index c225ea23..2b9f1f06 100644 --- a/public/static/images/canvas/shape/re_270deg/plane_tab01.svg +++ b/public/static/images/canvas/shape/re_270deg/plane_tab01.svg @@ -1,12 +1,16 @@ - - - - - - - - - - - + + + + + + + + + + + + + + + diff --git a/public/static/images/canvas/shape/re_90deg/plane_tab01.svg b/public/static/images/canvas/shape/re_90deg/plane_tab01.svg index 36c1d46b..b7cd5f4d 100644 --- a/public/static/images/canvas/shape/re_90deg/plane_tab01.svg +++ b/public/static/images/canvas/shape/re_90deg/plane_tab01.svg @@ -1,12 +1,16 @@ - - - - - - - - - - - + + + + + + + + + + + + + + + diff --git a/public/static/images/canvas/shape/re_normal/plane_tab01.svg b/public/static/images/canvas/shape/re_normal/plane_tab01.svg index 8fc73ac0..77db4276 100644 --- a/public/static/images/canvas/shape/re_normal/plane_tab01.svg +++ b/public/static/images/canvas/shape/re_normal/plane_tab01.svg @@ -1,14 +1,16 @@ - - - - - - - - - - - + + + + + + + + + + + + + + + diff --git a/qcast3.database.sqlite b/qcast3.database.sqlite new file mode 100644 index 00000000..c0c43e6f Binary files /dev/null and b/qcast3.database.sqlite differ diff --git a/src/app/GlobalDataProvider.js b/src/app/GlobalDataProvider.js index 4f6eabca..42c55fd8 100644 --- a/src/app/GlobalDataProvider.js +++ b/src/app/GlobalDataProvider.js @@ -3,32 +3,12 @@ import { createContext, useEffect, useState } from 'react' import { useLocalStorage } from 'usehooks-ts' -// export const GlobalDataContext = createContext({ -// managementState: {}, -// setManagementState: () => {}, -// managementStateLoaded: null, -// }) export const GlobalDataContext = createContext(null) const GlobalDataProvider = ({ children }) => { const [managementState, setManagementState] = useState(null) - // TODO: 임시 조치이며 개발 완료시 삭제 예정 -> 잊지말기... const [managementStateLoaded, setManagementStateLoaded] = useLocalStorage('managementStateLoaded', null) - // const pathname = usePathname() - // const setCorrentObjectNo = useSetRecoilState(correntObjectNoState) - // const searchParams = useSearchParams() - // const objectNo = searchParams.get('objectNo') - // const pid = searchParams.get('pid') - // useEffect(() => { - // if (pathname === '/floor-plan') { - // if (pid === undefined || pid === '' || pid === null || objectNo === undefined || objectNo === '' || objectNo === null) { - // notFound() - // } - // setCorrentObjectNo(objectNo) - // } - // }, [pathname]) - useEffect(() => { if (managementState !== null) { setManagementStateLoaded(managementState) diff --git a/src/app/QcastProvider.js b/src/app/QcastProvider.js index 73911177..fd2e3770 100644 --- a/src/app/QcastProvider.js +++ b/src/app/QcastProvider.js @@ -15,9 +15,7 @@ export const QcastContext = createContext({ }) export const QcastProvider = ({ children }) => { - const [planSave, setPlanSave] = useState(false) const [isGlobalLoading, setIsGlobalLoading] = useState(true) - const { commonCode, findCommonCode } = useCommonCode() const [qcastState, setQcastState] = useState({ saleStoreId: '', @@ -27,11 +25,6 @@ export const QcastProvider = ({ children }) => { businessChargerMail: null, }) - // useEffect(() => { - // console.log('commonCode', commonCode) - // console.log(findCommonCode(113600)) - // }, [commonCode, findCommonCode]) - return ( <> diff --git a/src/app/UIProvider.js b/src/app/UIProvider.js deleted file mode 100644 index 02a21441..00000000 --- a/src/app/UIProvider.js +++ /dev/null @@ -1,5 +0,0 @@ -import { NextUIProvider } from '@nextui-org/react' - -export default function UIProvider({ children }) { - return {children} -} diff --git a/src/app/api/html2canvas/route.js b/src/app/api/html2canvas/route.js deleted file mode 100644 index 21f93c82..00000000 --- a/src/app/api/html2canvas/route.js +++ /dev/null @@ -1,22 +0,0 @@ -'use server' - -import fs from 'fs/promises' - -import { NextResponse } from 'next/server' -import { writeImage, writeImageBuffer } from '@/lib/fileAction' - -export async function GET(req) { - const path = 'public/plan-map-images' - const q = req.nextUrl.searchParams.get('q') - const fileNm = req.nextUrl.searchParams.get('fileNm') - const zoom = req.nextUrl.searchParams.get('zoom') - const targetUrl = `https://maps.googleapis.com/maps/api/staticmap?center=${q}&zoom=${zoom}&maptype=satellite&size=640x640&scale=1&key=AIzaSyDO7nVR1N_D2tKy60hgGFavpLaXkHpiHpc` - const decodeUrl = decodeURIComponent(targetUrl) - - const response = await fetch(decodeUrl) - const data = await response.arrayBuffer() - const buffer = Buffer.from(data) - await writeImage(fileNm, buffer) - - return NextResponse.json({ fileNm: `${fileNm}.png` }) -} diff --git a/src/app/api/image-upload/route.js b/src/app/api/image-upload/route.js deleted file mode 100644 index 219544fe..00000000 --- a/src/app/api/image-upload/route.js +++ /dev/null @@ -1,15 +0,0 @@ -'use server' - -import { NextResponse } from 'next/server' -import { writeImage } from '@/lib/fileAction' - -export async function POST(req) { - const formData = await req.formData() - const file = formData.get('file') - const fileName = formData.get('fileName') - const arrayBuffer = await file.arrayBuffer() - const buffer = Buffer.from(arrayBuffer) - await writeImage(fileName, buffer) - - return NextResponse.json({ fileNm: `${fileName}.png` }) -} diff --git a/src/app/api/swr-tutorial/route.js b/src/app/api/swr-tutorial/route.js deleted file mode 100644 index 99ebaf15..00000000 --- a/src/app/api/swr-tutorial/route.js +++ /dev/null @@ -1,25 +0,0 @@ -import { NextResponse } from 'next/server' - -const defaultData = [ - { - id: 1, - name: 'John Doe', - email: 'john.doe@example.com', - }, - { - id: 2, - name: 'Jane Lee', - email: 'jane.lee@example.com', - }, -] - -export async function GET(req, res) { - return NextResponse.json(defaultData) -} - -export const POST = async (req, res) => { - const { id, name, email } = await req.json() - const newData = { id, name, email } - console.log('🚀 ~ POST ~ newData:', newData) - return NextResponse.json([...defaultData, newData]) -} diff --git a/src/app/community/archive/page.jsx b/src/app/community/archive/page.jsx index eee23c36..4713bb0b 100644 --- a/src/app/community/archive/page.jsx +++ b/src/app/community/archive/page.jsx @@ -1,4 +1,3 @@ -import Hero from '@/components/Hero' import Archive from '@/components/community/Archive' export default async function CommunityArchivePage() { diff --git a/src/app/initSettingsModal/page.jsx b/src/app/initSettingsModal/page.jsx deleted file mode 100644 index fc51b5cc..00000000 --- a/src/app/initSettingsModal/page.jsx +++ /dev/null @@ -1,13 +0,0 @@ -import Hero from '@/components/Hero' -import InitSettingsModal from '@/components/InitSettingsModal' - -export default async function InitSettingsModalPage() { - return ( - <> - -
- -
- - ) -} diff --git a/src/app/layout.js b/src/app/layout.js index 8071159a..a77f926c 100644 --- a/src/app/layout.js +++ b/src/app/layout.js @@ -16,11 +16,20 @@ import '../styles/contents.scss' import Footer from '@/components/footer/Footer' import GlobalLoadingProvider from './GlobalLoadingProvider' +/** + * 어플리케이션 메타데이터 + * 서버 컴포넌트에 한해서 개별로 설정할 수 있음 + */ export const metadata = { - title: 'Create Next App', - description: 'Generated by create next app', + title: 'HANASYS設計', + description: 'HANASYS設計', } +/** + * 어플리케이션 전체 레이아웃 컴포넌트 + * @param {*} param0 + * @returns + */ export default async function RootLayout({ children }) { const headersList = headers() const headerPathname = headersList.get('x-pathname') || '' diff --git a/src/app/management/plan/page.jsx b/src/app/management/plan/page.jsx deleted file mode 100644 index 51d67116..00000000 --- a/src/app/management/plan/page.jsx +++ /dev/null @@ -1,13 +0,0 @@ -import Hero from '@/components/Hero' -import Plan from '@/components/management/Plan' - -export default async function ManagementPlanPage() { - return ( - <> - -
- -
- - ) -} diff --git a/src/app/master/company/page.jsx b/src/app/master/company/page.jsx deleted file mode 100644 index 968452e8..00000000 --- a/src/app/master/company/page.jsx +++ /dev/null @@ -1,13 +0,0 @@ -import Hero from '@/components/Hero' -import Company from '@/components/master/Company' - -export default async function MasterCompanyPage() { - return ( - <> - -
- -
- - ) -} diff --git a/src/app/master/price/page.jsx b/src/app/master/price/page.jsx deleted file mode 100644 index 57fa0bd2..00000000 --- a/src/app/master/price/page.jsx +++ /dev/null @@ -1,13 +0,0 @@ -import Hero from '@/components/Hero' -import Price from '@/components/master/Price' - -export default async function MasterPricePage() { - return ( - <> - -
- -
- - ) -} diff --git a/src/app/playground/page.jsx b/src/app/playground/page.jsx deleted file mode 100644 index 3a3ad1d1..00000000 --- a/src/app/playground/page.jsx +++ /dev/null @@ -1,9 +0,0 @@ -import Playground from '@/components/Playground' - -export default async function PlaygroundPage() { - return ( - <> - - - ) -} diff --git a/src/app/roof/page.jsx b/src/app/roof/page.jsx deleted file mode 100644 index 960ffa89..00000000 --- a/src/app/roof/page.jsx +++ /dev/null @@ -1,13 +0,0 @@ -import Hero from '@/components/Hero' -import Roof from '@/components/Roof' - -export default async function RoofPage() { - return ( - <> - -
- -
- - ) -} diff --git a/src/app/roof2/page.jsx b/src/app/roof2/page.jsx deleted file mode 100644 index 94e86fbe..00000000 --- a/src/app/roof2/page.jsx +++ /dev/null @@ -1,11 +0,0 @@ -import Roof2 from '@/components/Roof2' - -export default async function Roof2Page() { - return ( - <> -
- -
- - ) -} diff --git a/src/app/settings/page.jsx b/src/app/settings/page.jsx deleted file mode 100644 index ab714682..00000000 --- a/src/app/settings/page.jsx +++ /dev/null @@ -1,13 +0,0 @@ -import Hero from '@/components/Hero' -import Settings from '@/components/Settings' - -export default async function SettingsPage() { - return ( - <> - -
- -
- - ) -} diff --git a/src/common/common.js b/src/common/common.js index 9aad21d6..d82d43f0 100644 --- a/src/common/common.js +++ b/src/common/common.js @@ -116,6 +116,15 @@ export const POLYGON_TYPE = { OBJECT_SURFACE: 'objectOffset', } +// 가대 관련 상수 +export const TRESTLE_MATERIAL = { + EAVE_BAR: 'eaveBar', + HALF_EAVE_BAR: 'halfEaveBar', + RACK: 'rack', + SMART_RACK: 'smartRack', + BRACKET: 'bracket', +} + export const SAVE_KEY = [ 'selectable', 'name', @@ -187,6 +196,13 @@ export const SAVE_KEY = [ 'circuit', 'onlyOffset', 'isChidory', + 'textVisible', + 'groupPoints', + 'fontSize', + 'fontStyle', + 'fontWeight', + 'dormerAttributes', + 'toFixed', ] -export const OBJECT_PROTOTYPE = [fabric.Line.prototype, fabric.Polygon.prototype, fabric.Triangle.prototype] +export const OBJECT_PROTOTYPE = [fabric.Line.prototype, fabric.Polygon.prototype, fabric.Triangle.prototype, fabric.Group.prototype] diff --git a/src/components/GridSettingsModal.jsx b/src/components/GridSettingsModal.jsx deleted file mode 100644 index 92b2e618..00000000 --- a/src/components/GridSettingsModal.jsx +++ /dev/null @@ -1,273 +0,0 @@ -import { useEffect, useRef, useState } from 'react' -import { Button, Checkbox, CheckboxGroup, RadioGroup, Radio, Input } from '@nextui-org/react' -import { useRecoilState, useRecoilValue } from 'recoil' -import { modalContent, modalState } from '@/store/modalAtom' -import { guideLineState, horiGuideLinesState, vertGuideLinesState } from '@/store/canvasAtom' -import { fabric } from 'fabric' -import { ColorPicker, useColor } from 'react-color-palette' -import 'react-color-palette/css' -import { gridColorState } from '@/store/gridAtom' - -export default function GridSettingsModal(props) { - const { canvasProps } = props - const [isCustomGridSetting, setIsCustomGridSetting] = useState(true) - const [gridCheckedValue, setGridCheckValue] = useState([]) - const [ratioValue, setRatioValue] = useState('1') - const moduleLength = useRef(null) //모듈 mm 길이 입력 - const customModuleHoriLength = useRef(null) - const customModuleVertLength = useRef(null) - - const [open, setOpen] = useRecoilState(modalState) - const [guideLine, setGuideLine] = useRecoilState(guideLineState) - const [horiGuideLines, setHoriGuideLines] = useRecoilState(horiGuideLinesState) - const [vertGuideLines, setVertGuideLines] = useRecoilState(vertGuideLinesState) - - const gridSettingArray = [] - - const gridColor = useRecoilValue(gridColorState) - const [colorPickerShow, setColorPickerShow] = useState(false) - - const boxStyle = { - width: '50px', - height: '30px', - border: '1px solid black', - backgroundColor: guideColor.hex, - } - useEffect(() => { - moduleLength.current.value = 90 - customModuleHoriLength.current.value = 90 - customModuleVertLength.current.value = 90 - }, []) - - useEffect(() => { - setIsCustomGridSetting(ratioValue !== 'custom') - }, [ratioValue]) - - const drawGridSettings = () => { - //기존에 선택된 데이터가 있으면 그 데이터를 포함한다 - if (!(Object.keys(guideLine).length === 0 && guideLine.constructor === Object)) { - gridSettingArray.push(...guideLine) - } - - let moduleHoriLength = moduleLength.current.value //가로 간격 - let moduleVertLength = moduleLength.current.value //새로 간격 - - if (ratioValue === 'custom') { - moduleHoriLength = customModuleHoriLength.current.value - moduleVertLength = customModuleVertLength.current.value - } else { - moduleHoriLength = moduleHoriLength / ratioValue - moduleVertLength = moduleVertLength / ratioValue - } - - if (gridCheckedValue.includes('line')) { - const horizontalLineArray = [] - const verticalLineArray = [] - - for (let i = 0; i < canvasProps.height / moduleVertLength + 1; i++) { - const horizontalLine = new fabric.Line( - [0, i * moduleVertLength - moduleVertLength / 2, canvasProps.width, i * moduleVertLength - moduleVertLength / 2], - { - stroke: gridColor, - strokeWidth: 1, - selectable: true, - lockMovementX: true, - lockMovementY: true, - lockRotation: true, - lockScalingX: true, - lockScalingY: true, - name: 'guideLine', - strokeDashArray: [5, 2], - opacity: 0.3, - direction: 'horizontal', - }, - ) - canvasProps.add(horizontalLine) - horizontalLineArray.push(horizontalLine) - } - - for (let i = 0; i < canvasProps.width / moduleHoriLength + 1; i++) { - const verticalLine = new fabric.Line( - [i * moduleHoriLength - moduleHoriLength / 2, 0, i * moduleHoriLength - moduleHoriLength / 2, canvasProps.height], - { - stroke: gridColor, - strokeWidth: 1, - selectable: true, - lockMovementX: true, - lockMovementY: true, - lockRotation: true, - lockScalingX: true, - lockScalingY: true, - name: 'guideLine', - strokeDashArray: [5, 2], - opacity: 0.3, - direction: 'vertical', - }, - ) - canvasProps.add(verticalLine) - verticalLineArray.push(verticalLine) - } - canvasProps.renderAll() - - const snapDistance = 10 - - const recoilObj = { - guideMode: 'guideLine', - horizontalLineArray, - verticalLineArray, - moduleVertLength: moduleVertLength, - moduleHoriLength: moduleHoriLength, - } - gridSettingArray.push(recoilObj) - const newHoriGuideLines = [...horiGuideLines] - horizontalLineArray.forEach((line) => { - newHoriGuideLines.push(line) - }) - const newVertGuideLines = [...vertGuideLines] - verticalLineArray.forEach((line) => { - newVertGuideLines.push(line) - }) - setHoriGuideLines(newHoriGuideLines) - setVertGuideLines(newVertGuideLines) - } - - if (gridCheckedValue.includes('dot')) { - const circle = new fabric.Circle({ - radius: 2, - fill: 'white', - stroke: guideColor.hex, - strokeWidth: 0.7, - originX: 'center', - originY: 'center', - selectable: false, - lockMovementX: true, - lockMovementY: true, - lockRotation: true, - lockScalingX: true, - lockScalingY: true, - }) - - const patternSourceCanvas = new fabric.StaticCanvas(null, { - width: moduleHoriLength, - height: moduleVertLength, - }) - - patternSourceCanvas.add(circle) - - circle.set({ - left: patternSourceCanvas.width / 2, - top: patternSourceCanvas.height / 2, - }) - - patternSourceCanvas.renderAll() - - const pattern = new fabric.Pattern({ - source: patternSourceCanvas.getElement(), - repeat: 'repeat', - }) - - const backgroundPolygon = new fabric.Polygon( - [ - { x: 0, y: 0 }, - { x: canvasProps.width, y: 0 }, - { x: canvasProps.width, y: canvasProps.height }, - { x: 0, y: canvasProps.height }, - ], - { - fill: pattern, - selectable: false, - name: 'guideDot', - }, - ) - - canvasProps.add(backgroundPolygon) - backgroundPolygon.sendToBack() - canvasProps.renderAll() - - const recoilObj = { - guideMode: 'guideDot', - moduleVertLength: moduleVertLength, - moduleHoriLength: moduleHoriLength, - } - - gridSettingArray.push(recoilObj) - } - canvasProps.renderAll() - setGuideLine(gridSettingArray) - } - - const removeGuideLines = () => { - if (!(Object.keys(guideLine).length === 0 && guideLine.constructor === Object)) { - const guideLines = canvasProps._objects.filter((obj) => obj.name === 'guideLine' || obj.name === 'guideDot') - guideLines?.forEach((item) => canvasProps.remove(item)) - canvasProps.renderAll() - setGuideLine([]) - setHoriGuideLines([]) - setVertGuideLines([]) - } else { - alert('그리드가 없습니다.') - return - } - } - - return ( - <> -
-
- -
-
- - mm -
-
- - 원치수 - 1/2 - 1/4 - 1/10 - 임의간격 - -
-
- 가이드컬러
setColorPickerShow(!colorPickerShow)}>
-
- {colorPickerShow && ( - - )} - -
- - 종횡연동 - -
-
-
- - mm -
-
- - mm -
- -
- - - - -
- - ) -} diff --git a/src/components/Headers.jsx b/src/components/Headers.jsx deleted file mode 100644 index 02859c96..00000000 --- a/src/components/Headers.jsx +++ /dev/null @@ -1,21 +0,0 @@ -import Link from 'next/link' - -export default function Headers() { - return ( -
- -
- ) -} diff --git a/src/components/Hero.jsx b/src/components/Hero.jsx deleted file mode 100644 index a6e7761f..00000000 --- a/src/components/Hero.jsx +++ /dev/null @@ -1,7 +0,0 @@ -export default function Hero(props) { - return ( -
-

{props.title}

-
- ) -} diff --git a/src/components/InitSettingsModal.jsx b/src/components/InitSettingsModal.jsx deleted file mode 100644 index 52c82e86..00000000 --- a/src/components/InitSettingsModal.jsx +++ /dev/null @@ -1,255 +0,0 @@ -'use client' - -import { useEffect, useState, memo, useCallback } from 'react' -import { Button, Checkbox, CheckboxGroup, RadioGroup, Radio, Input, Select, SelectItem } from '@nextui-org/react' -import { useRecoilState, useRecoilValue } from 'recoil' -import { modalContent, modalState } from '@/store/modalAtom' -import { canvasSettingState } from '@/store/canvasAtom' -import { useAxios } from '@/hooks/useAxios' - -export default function InitSettingsModal(props) { - const [objectNo, setObjectNo] = useState('test123240909003') // 후에 삭제 필요 - const [open, setOpen] = useRecoilState(modalState) - const [canvasSetting, setCanvasSetting] = useRecoilState(canvasSettingState) - const [roofMaterials, setRoofMaterials] = useState([]) - const [basicSetting, setBasicSettings] = useState({ - roofDrawingSet: '1', - roofSizeSet: '1', - roofAngleSet: 'slope', - roofs: [{ roofSeq: '1', roofType: '3', roofWidth: '200', roofHeight: '200', roofGap: '0', roofLayout: 'parallel' }], - }) - - const modelProps = { - open, - setOpen, - } - - const { get, post } = useAxios() - - //const { get, post } = useAxios() - - useEffect(() => { - get({ url: `/api/canvas-management/canvas-basic-settings/by-object/${objectNo}` }).then((res) => { - if (res.length == 0) return - - // 'roofs' 배열을 생성하여 각 항목을 추가 - const roofsRow = res.map((item) => { - return { - roofDrawingSet: String(item.roofDrawingSet), - roofSizeSet: String(item.roofSizeSet), - roofAngleSet: item.roofAngleSet, - } - }) - - const roofsArray = res.some((item) => !item.roofSeq) - ? //최초 지붕재 추가 정보의 경우 roofsArray를 초기화 설정 - [{ roofSeq: '1', roofType: '3', roofWidth: '200', roofHeight: '200', roofGap: '0', roofLayout: 'parallel' }] - : res.map((item) => ({ - roofSeq: String(item.roofSeq), - roofType: String(item.roofType), - roofWidth: String(item.roofWidth), - roofHeight: String(item.roofHeight), - roofGap: String(item.roofGap), - roofLayout: item.roofLayout, - })) - - // 나머지 데이터와 함께 'roofs' 배열을 patternData에 넣음 - const patternData = { - roofDrawingSet: roofsRow[0].roofDrawingSet, // 첫 번째 항목의 값을 사용 - roofSizeSet: roofsRow[0].roofSizeSet, // 첫 번째 항목의 값을 사용 - roofAngleSet: roofsRow[0].roofAngleSet, // 첫 번째 항목의 값을 사용 - roofs: roofsArray, // 만들어진 roofs 배열 - } - - // 데이터 설정 - setBasicSettings({ ...patternData }) - }) - - if (!(Object.keys(canvasSetting).length === 0 && canvasSetting.constructor === Object)) { - setBasicSettings({ ...canvasSetting }) - } - }, []) - - //기본 설정값 변경 함수 - const handleBasicSetting = (event) => { - const newBasicSetting = { ...basicSetting, [event.target.name]: event.target.value } - setBasicSettings(newBasicSetting) - } - - //배열 값 변경 함수 - const handleRoofSettings = (id, event) => { - // 기본 세팅에서 roofs 배열을 복사 - const updatedRoofs = [...basicSetting.roofs] - - // roofSeq가 id와 일치하는 항목의 인덱스 찾기 - const index = updatedRoofs.findIndex((roof) => roof.roofSeq === id) - - if (index !== -1) { - // 해당 인덱스의 항목을 수정 - updatedRoofs[index] = { - ...updatedRoofs[index], - [event.target.name]: event.target.value, - } - - // 수정된 배열을 상태에 반영 - setBasicSettings((prevState) => ({ - ...prevState, - roofs: updatedRoofs, - })) - } - } - - //저장 - const submitCanvasConfig = async () => { - if (!objectNo) { - alert('object_no를 입력하세요.') - return - } - - const patternData = { - objectNo, - roofDrawingSet: basicSetting.roofDrawingSet, - roofSizeSet: basicSetting.roofSizeSet, - roofAngleSet: basicSetting.roofAngleSet, - roofMaterialsAddList: basicSetting.roofs, - } - await post({ url: `/api/canvas-management/canvas-basic-settings`, data: patternData }) - - //Recoil 설정 - setCanvasSetting({ ...basicSetting }) - - // 저장 후 재조회 - //await handleSelect() - } - - return ( - <> -
-
배치면 초기설정
- -
-
- - 치수 입력에 의한 물건작성 - -
-
- -
-
- - 복사도 입력 - 실측값 입력 - 육지붕 - -
-
- -
-
- - 경사 - 각도 - -
-
- - {/* Roofs Array Rendering */} - {basicSetting.roofs && - basicSetting.roofs.map((roof, index) => { - return ( -
- 타입 : - - 너비 : - handleRoofSettings(roof.roofSeq, e)} - /> - mm - 높이 : - handleRoofSettings(roof.roofSeq, e)} - /> - mm - 서까래 간격 : - handleRoofSettings(roof.roofSeq, e)} - /> - mm -
- handleRoofSettings(roof.roofSeq, e)} - > - 병렬식 - 계단식 - -
-
- ) - })} - -
- - - setObjectNo(e.target.value)} /> -
-
- - ) -} diff --git a/src/components/Playground.jsx b/src/components/Playground.jsx deleted file mode 100644 index 8a365646..00000000 --- a/src/components/Playground.jsx +++ /dev/null @@ -1,919 +0,0 @@ -'use client' - -import { useRef, useState, useEffect, useContext } from 'react' -import Image from 'next/image' -import { useRecoilState } from 'recoil' -import { v4 as uuidv4 } from 'uuid' -import { FaAnglesUp } from 'react-icons/fa6' -import { FaAnglesDown } from 'react-icons/fa6' -import { Button } from '@nextui-org/react' -import ColorPicker from './common/color-picker/ColorPicker' -import { cadFileNameState, googleMapFileNameState, useCadFileState, useGoogleMapFileState } from '@/store/canvasAtom' - -import { useAxios } from '@/hooks/useAxios' -import { useMessage } from '@/hooks/useMessage' -import { useMasterController } from '@/hooks/common/useMasterController' -import { useSwal } from '@/hooks/useSwal' -import { convertDwgToPng } from '@/lib/cadAction' -import { GlobalDataContext } from '@/app/GlobalDataProvider' -import QInput from './common/input/Qinput' -import QSelect from './common/select/QSelect' -import QPagination from './common/pagination/QPagination' -import QSelectBox from './common/select/QSelectBox' -import SampleReducer from './sample/SampleReducer' - -import styles from './playground.module.css' -import useSWR from 'swr' -import useSWRMutation from 'swr/mutation' -import { useCanvasPopupStatusController } from '@/hooks/common/useCanvasPopupStatusController' -import { canvasPopupStatusStore } from '@/store/canvasPopupStatusAtom' -import { moduleSelectionDataPlanListState } from '@/store/selectedModuleOptions' -import { useRouter } from 'next/navigation' -import { QcastContext } from '@/app/QcastProvider' - -export default function Playground() { - const [useCadFile, setUseCadFile] = useRecoilState(useCadFileState) - const [cadFileName, setCadFileName] = useRecoilState(cadFileNameState) - const [useGoogleMapFile, setUseGoogleMapFile] = useRecoilState(useGoogleMapFileState) - const [googleMapFileName, setGoogleMapFileName] = useRecoilState(googleMapFileNameState) - const fileRef = useRef(null) - const queryRef = useRef(null) - const [zoom, setZoom] = useState(20) - const { get, promiseGet, post, promisePost, getFetcher, postFetcher } = useAxios() - const testVar = process.env.NEXT_PUBLIC_TEST - const converterUrl = process.env.NEXT_PUBLIC_CONVERTER_API_URL - const { getMessage } = useMessage() - const { swalFire } = useSwal() - const { getRoofMaterialList, getModuleTypeItemList, getTrestleList, getConstructionList, getTrestleDetailList } = useMasterController() - - const [color, setColor] = useState('#ff0000') - - const [textInput, setTextInput] = useState('') - const [numberInput, setNumberInput] = useState('') - const [radioInput, setRadioInput] = useState('') - const [checkboxInput, setCheckboxInput] = useState([]) - const [selectedValue, setSelectedValue] = useState('') - - const [users, setUsers] = useState([]) - - const { managementState, setManagementState, managementStateLoaded } = useContext(GlobalDataContext) - - const router = useRouter() - const { setIsGlobalLoading } = useContext(QcastContext) - - useEffect(() => { - setIsGlobalLoading(false) - }, []) - - useEffect(() => { - console.log('textInput:', textInput) - }, [textInput]) - useEffect(() => { - console.log('numberInput:', numberInput) - }, [numberInput]) - useEffect(() => { - console.log('radioInput:', radioInput) - }, [radioInput]) - useEffect(() => { - console.log('checkboxInput:', checkboxInput) - }, [checkboxInput]) - useEffect(() => { - console.log('selectedValue:', selectedValue) - }, [selectedValue]) - - const handleUsers = async () => { - // const users = await get('/api/user/find-all') - const params = { - url: '/api/user/find-all', - } - const users = await get(params) - console.log('users', users) - } - - const handleConvert = async () => { - console.log('file', fileRef.current.files[0]) - - const formData = new FormData() - formData.append('file', fileRef.current.files[0]) - - await promisePost({ url: converterUrl, data: formData }) - .then((res) => { - console.log('response: ', res) - convertDwgToPng(res.data.Files[0].FileName, res.data.Files[0].FileData) - setUseCadFile(true) - setCadFileName(res.data.Files[0].FileName) - swalFire({ text: '파일 변환 완료' }) - }) - .catch((err) => { - console.error(err) - swalFire({ text: '파일 변환 실패' }) - }) - } - - const handleDownImage = async (fileName = '') => { - const fileNm = fileName === '' ? uuidv4() : fileName - const queryString = queryRef.current.value === '' ? '서울시 서대문구 연세로5다길 22-3 발리빌라 3층' : queryRef.current.value - const res = await get({ url: `http://localhost:3000/api/html2canvas?q=${queryString}&fileNm=${fileNm}&zoom=${zoom}` }) - console.log('res', res) - setGoogleMapFileName(res.fileNm) - swalFire({ text: '이미지 저장 완료' }) - setUseGoogleMapFile(true) - } - - const handleZoom = async (type) => { - if (type === 'up') { - setZoom((prevState) => prevState + 1) - } else { - setZoom((prevState) => prevState - 1) - } - - await handleDownImage() - } - - const data = [ - { - id: 1, - author: 'SWYOO', - contents: '버튼 정리(템플릿 적용)', - date: '2024.07.16', - }, - { - id: 2, - author: 'SWYOO', - contents: 'README.md 파일 이미지 경로 수정', - date: '2024.07.17', - }, - { - id: 3, - author: 'SWYOO', - contents: '', - date: '', - }, - ] - - const handleSwalAlert = () => { - swalFire({ - text: '알림 테스트입니다.', - }) - } - - const paginationProps = { - pageNo: 1, - pageSize: 10, - pagePerBlock: 10, - totalCount: 26, - handleChangePage: (page) => { - console.log('page', page) - }, - } - - useEffect(() => { - console.log('users:', users) - }, [users]) - - const codes = [ - { - clHeadCd: '203800', - clCode: 'HEI_455', - clCodeNm: '세로 455mm이하', - clPriority: 1, - name: '세로 455mm이하', - id: 'HEI_455', - }, - { - clHeadCd: '203800', - clCode: 'HEI_500', - clCodeNm: '세로 500mm이하', - clPriority: 2, - name: '세로 500mm이하', - id: 'HEI_500', - }, - { - clHeadCd: '203800', - clCode: 'HEI_606', - clCodeNm: '세로 606mm이하', - clPriority: 3, - name: '세로 606mm이하', - id: 'HEI_606', - }, - { - clHeadCd: '203800', - clCode: 'WID_606', - clCodeNm: '가로 606mm이하', - clPriority: 4, - name: '가로 606mm이하', - id: 'WID_606', - }, - { - clHeadCd: '203800', - clCode: 'ETC', - clCodeNm: '기타', - clPriority: 5, - name: '기타', - id: 'ETC', - }, - ] - - const [myData, setMyData] = useState({ - roofMatlCd: 'ROOF_ID_WA_53A', - roofMatlNm: '화와 A', - roofMatlNmJp: '和瓦A', - widAuth: 'R', - widBase: '265.000', - lenAuth: 'R', - lenBase: '235.000', - roofPchAuth: null, - roofPchBase: null, - raftAuth: 'C', - raftBaseCd: 'HEI_455', - id: 'ROOF_ID_WA_53A', - name: '화와 A', - selected: true, - nameJp: '和瓦A', - length: 235, - width: 265, - layout: 'P', - hajebichi: null, - }) - - const handleChangeMyData = () => { - setMyData({ ...myData, raftBaseCd: 'HEI_500' }) - } - - const [myData2, setMyData2] = useState({}) - - const handleChangeMyData2 = () => { - setMyData2({ - roofMatlCd: 'ROOF_ID_WA_53A', - roofMatlNm: '화와 A', - roofMatlNmJp: '和瓦A', - widAuth: 'R', - widBase: '265.000', - lenAuth: 'R', - lenBase: '235.000', - roofPchAuth: null, - roofPchBase: null, - raftAuth: 'C', - raftBaseCd: 'HEI_455', - id: 'ROOF_ID_WA_53A', - name: '화와 A', - selected: true, - nameJp: '和瓦A', - length: 235, - width: 265, - layout: 'P', - hajebichi: null, - }) - } - - // const [callFlag, setCallFlag] = useState(false) - // const { data: tutoData, error, isLoading } = useSWR('http://localhost:8080/api/tutorial', getFetcher) - // const { data: tutoData, error, isLoading } = useSWR(callFlag ? 'http://localhost:8080/api/tutorial' : null, getFetcher) - // const { trigger, isMutating } = useSWRMutation('http://localhost:8080/api/tutorial', postFetcher) - - // if (isLoading) { - // return
Loading...
- // } - - // if (error) { - // return
Error...
- // } - - // const [moduleSelectionDataPlanListStore, setModuleSelectionDataPlanListStore] = useRecoilState(moduleSelectionDataPlanListState) - // useEffect(() => { - // console.log('🚀 ~ Playground ~ moduleSelectionDataPlanListStore:', moduleSelectionDataPlanListStore) - // }, [moduleSelectionDataPlanListStore]) - // const { trigger: canvasPopupStatusTrigger } = useCanvasPopupStatusController({ objectNo: 'R201T01241120001', planNo: 2, popupType: 2 }) - - return ( - <> -
-
이 영역은 테스트입니다.
-
- {' '} - {' '} - {' '} - {' '} - -
- -
- - - -
- - - -
- - -
- - -
-
-
- - - - -
-
{testVar}
-
-
- -
-
-
-

Sass 테스트입니다.

-
-
test']) }}>
-
-

React ColorPicker

- -
{color}
-
-
-

캐드 파일 이미지 사용

- -
- -
-
-
-

구글 맵 이미지 사용

- -
- -
- {useGoogleMapFile && ( - <> -
-

Zoom Controller : {zoom}

- - -
-
- -
- - )} -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
- {/*
-

{managementStateLoaded?.objectNo}

-
*/} -
- -
- {/*
- {tutoData && - tutoData.map((item) => ( -
- {item.name} / {item.email} -
- ))} -
-
- -
-
- -
*/} -
- -
-
- -
-
- - ) -} diff --git a/src/components/Roof.jsx b/src/components/Roof.jsx deleted file mode 100644 index 51ba639e..00000000 --- a/src/components/Roof.jsx +++ /dev/null @@ -1,351 +0,0 @@ -'use client' - -import { useEffect } from 'react' -import { addDistanceTextToPolygon, getDistance } from '@/util/canvas-util' -import { useCanvas } from '@/hooks/useCanvas' -import { fabric } from 'fabric' -import { v4 as uuidv4 } from 'uuid' - -export default function Roof() { - const { - canvas, - addShape, - handleUndo, - handleRedo, - handleClear, - handleCopy, - handleDelete, - handleSave, - handlePaste, - handleRotate, - attachCustomControlOnPolygon, - saveImage, - handleFlip, - } = useCanvas('canvas') - - useEffect(() => { - let circle = new fabric.Circle({ - radius: 40, - fill: 'rgba(200, 0, 0, 0.3)', - originX: 'center', - originY: 'center', - }) - - let text = new fabric.Textbox('AJLoveChina', { - originX: 'center', - originY: 'center', - textAlign: 'center', - fontSize: 12, - }) - - let group = new fabric.Group([circle, text], { - left: 100, - top: 100, - originX: 'center', - originY: 'center', - }) - - group.on('mousedblclick', () => { - // textForEditing is temporary obj, - // and will be removed after editing - console.log(text.type) - let textForEditing = new fabric.Textbox(text.text, { - originX: 'center', - originY: 'center', - textAlign: text.textAlign, - fontSize: text.fontSize, - - left: group.left, - top: group.top, - }) - - // hide group inside text - text.visible = false - // note important, text cannot be hidden without this - group.addWithUpdate() - - textForEditing.visible = true - // do not give controls, do not allow move/resize/rotation on this - textForEditing.hasConstrols = false - - // now add this temporary obj to canvas - canvas.add(textForEditing) - canvas.setActiveObject(textForEditing) - // make the cursor showing - textForEditing.enterEditing() - textForEditing.selectAll() - - // editing:exited means you click outside of the textForEditing - textForEditing.on('editing:exited', () => { - let newVal = textForEditing.text - let oldVal = text.text - - // then we check if text is changed - if (newVal !== oldVal) { - text.set({ - text: newVal, - visible: true, - }) - - // comment before, you must call this - group.addWithUpdate() - - // we do not need textForEditing anymore - textForEditing.visible = false - canvas?.remove(textForEditing) - - // optional, buf for better user experience - canvas?.setActiveObject(group) - } - }) - }) - - canvas?.add(group) - }, [canvas]) - - const addRect = () => { - const rect = new fabric.Rect({ - height: 200, - width: 200, - top: 10, - left: 10, - opacity: 0.4, - fill: randomColor(), - stroke: 'red', - name: uuidv4(), - }) - - addShape(rect) - } - - const addHorizontalLine = () => { - const { x1, y1, x2, y2 } = { x1: 20, y1: 100, x2: 220, y2: 100 } - /** - * 시작X,시작Y,도착X,도착Y 좌표 - */ - const horizontalLine = new fabric.Line([x1, y1, x2, y2], { - name: uuidv4(), - stroke: 'red', - strokeWidth: 3, - selectable: true, - }) - - const text = new fabric.Text(getDistance(x1, y1, x2, y2).toString(), { - fontSize: 20, - left: (x2 - x1) / 2, - top: y1 - 20, - }) - - const group = new fabric.Group([horizontalLine, text], { - left: 20, - top: 20, - }) - - // addShape(horizontalLine) - addShape(group) - console.log(JSON.stringify(canvas)) - } - - const addVerticalLine = () => { - const verticalLine = new fabric.Line([10, 10, 10, 100], { - name: uuidv4(), - stroke: 'red', - strokeWidth: 3, - selectable: true, - }) - - addShape(verticalLine) - } - - const addTriangle = () => { - const triangle = new fabric.Triangle({ - name: uuidv4(), - top: 50, - left: 50, - width: 100, - stroke: randomColor(), - strokeWidth: 3, - }) - - addShape(triangle) - } - - const addTrapezoid = () => { - const trapezoid = new fabric.Polygon( - [ - { x: 100, y: 100 }, // 좌상단 - { x: 500, y: 100 }, // 우상단 - { x: 750, y: 700 }, // 우하단 - { x: 250, y: 400 }, // 좌하단 - ], - { - name: uuidv4(), - stroke: 'red', - opacity: 0.4, - strokeWidth: 3, - selectable: true, - objectCaching: false, - }, - ) - attachCustomControlOnPolygon(trapezoid) - const group = addDistanceTextToPolygon(trapezoid) - addGroupClickEvent(group) - canvas?.add(group) - canvas?.renderAll() - } - - // group에 클릭 이벤트를 추가하여 클릭 시 group을 제거하고 object들만 남기는 함수 - function addGroupClickEvent(group) { - group.on('selected', (e) => { - console.log(e) - }) - group.on('mousedblclick', (e) => { - // textForEditing is temporary obj, - // and will be removed after editing - const pointer = canvas?.getPointer(e.e) // 마우스 클릭 위치 가져오기 - let minDistance = Infinity - let closestTextbox = null - const groupPoint = group.getCenterPoint() - group.getObjects().forEach(function (object) { - if (object.type === 'textbox') { - // 객체가 TextBox인지 확인 - - const objectCenter = object.getCenterPoint() // TextBox 객체의 중심점 가져오기 - const dx = objectCenter.x + groupPoint.x - pointer.x - const dy = objectCenter.y + groupPoint.y - pointer.y - const distance = Math.sqrt(dx * dx + dy * dy) // 마우스 클릭 위치와 TextBox 객체 사이의 거리 계산 - - if (distance < minDistance) { - // 가장 짧은 거리를 가진 TextBox 객체 찾기 - minDistance = distance - closestTextbox = object - } - } - }) - - let textForEditing = new fabric.Textbox(closestTextbox.text, { - originX: 'center', - originY: 'center', - textAlign: closestTextbox.textAlign, - fontSize: closestTextbox.fontSize, - left: closestTextbox.left + groupPoint.x, - top: closestTextbox.top + groupPoint.y, - }) - - // hide group inside text - closestTextbox.visible = false - // note important, text cannot be hidden without this - group.addWithUpdate() - - textForEditing.visible = true - // do not give controls, do not allow move/resize/rotation on this - textForEditing.hasConstrols = false - - // now add this temporary obj to canvas - canvas?.add(textForEditing) - canvas?.setActiveObject(textForEditing) - // make the cursor showing - textForEditing?.enterEditing() - textForEditing?.selectAll() - - // editing:exited means you click outside of the textForEditing - textForEditing?.on('editing:exited', () => { - let newVal = textForEditing.text - - // then we check if text is changed - closestTextbox.set({ - text: newVal, - visible: true, - }) - - // comment before, you must call this - group.addWithUpdate() - - // we do not need textForEditing anymore - textForEditing.visible = false - canvas?.remove(textForEditing) - - // optional, buf for better user experience - canvas?.setActiveObject(group) - }) - }) - } - - // IText를 수정할 때 해당 값을 길이로 갖는 다른 polygon을 생성하고 다시 그룹화하는 함수 - function addTextModifiedEvent(text, polygon, index) { - text.on('editing:exited', function () {}) - } - - const randomColor = () => { - return '#' + Math.round(Math.random() * 0xffffff).toString(16) - } - - return ( - <> -
- - - - - - - - - - - - - - - -
- -
- -
- - ) -} diff --git a/src/components/Roof2.jsx b/src/components/Roof2.jsx deleted file mode 100644 index 731fe8c6..00000000 --- a/src/components/Roof2.jsx +++ /dev/null @@ -1,1099 +0,0 @@ -'use client' - -import { useCanvas } from '@/hooks/useCanvas' -import { useEffect, useRef, useState } from 'react' -import { v4 as uuidv4 } from 'uuid' -import { useMode } from '@/hooks/useMode' -import { LINE_TYPE, Mode } from '@/common/common' -import { Button } from '@nextui-org/react' -import RangeSlider from './ui/RangeSlider' -import { useRecoilState, useRecoilValue } from 'recoil' -import { - cadFileCompleteState, - cadFileNameState, - canvasSizeState, - compassState, - currentObjectState, - fontSizeState, - globalCompassState, - googleMapFileNameState, - roofMaterialState, - roofState, - sortedPolygonArray, - templateTypeState, - useCadFileState, - useGoogleMapFileState, - wallState, -} from '@/store/canvasAtom' -import { QLine } from '@/components/fabric/QLine' -import { getCanvasState, insertCanvasState } from '@/lib/canvas' -import { calculateIntersection } from '@/util/canvas-util' -import { QPolygon } from '@/components/fabric/QPolygon' -import QContextMenu from './common/context-menu/QContextMenu' -import { modalContent, modalState } from '@/store/modalAtom' -import { useAxios } from '@/hooks/useAxios' -import QPolygonContextMenu from '@/components/common/context-menu/QPolygonContextMenu' -import QLineContextMenu from '@/components/common/context-menu/QLineContextMenu' -import QEmptyContextMenu from '@/components/common/context-menu/QEmptyContextMenu' - -import InitSettingsModal from './InitSettingsModal' -import GridSettingsModal from './GridSettingsModal' -import { SurfaceShapeModal } from '@/components/ui/SurfaceShape' -import { changeCurrentRoof, drawDirectionStringToArrow } from '@/util/qpolygon-utils' -import ThumbnailList from '@/components/ui/ThumbnailLIst' -import ObjectPlacement from '@/components/ui/ObjectPlacement' -import { globalLocaleStore } from '@/store/localeAtom' - -export default function Roof2(props) { - const { name, userId, email, isLoggedIn } = props - const { - canvas, - handleRedo, - handleUndo, - setCanvasBackgroundWithDots, - saveImage, - addCanvas, - handleBackImageLoadToCanvas, - handleCadImageInit, - backImg, - setBackImg, - } = useCanvas('canvas') - - const globalLocaleState = useRecoilValue(globalLocaleStore) - - const { get } = useAxios(globalLocaleState) - - const canvasRef = useRef(null) - - //canvas 기본 사이즈 - const [canvasSize, setCanvasSize] = useRecoilState(canvasSizeState) - - //canvas 가로 사이즈 - const [verticalSize, setVerticalSize] = useState(canvasSize.vertical) - //canvas 세로 사이즈 - const [horizontalSize, setHorizontalSize] = useState(canvasSize.horizontal) - // 글자크기 - const [fontSize, setFontSize] = useRecoilState(fontSizeState) - - const [sortedArray] = useRecoilState(sortedPolygonArray) - - const [angle, setAngle] = useState(0) - - const [showControl, setShowControl] = useState(false) - - //지붕재 - const roofMaterial = useRecoilValue(roofMaterialState) - - const [templateType, setTemplateType] = useRecoilState(templateTypeState) - - const [compass, setCompass] = useRecoilState(compassState) - - const roof = useRecoilValue(roofState) - - const wall = useRecoilValue(wallState) - - const [open, setOpen] = useRecoilState(modalState) - const [contents, setContent] = useRecoilState(modalContent) - - const [scale, setScale] = useState(1) - const currentObject = useRecoilValue(currentObjectState) - - //canvas 썸네일 - const [thumbnails, setThumbnails] = useState([]) - const thumbnailProps = { - thumbnails, - canvas, - } - - let imgPath - // cad 파일 업로드 - const [useCadFile, setUseCadFile] = useRecoilState(useCadFileState) - const [cadFileName, setCadFileName] = useRecoilState(cadFileNameState) - const [cadFileComplete, setCadFileComplete] = useRecoilState(cadFileCompleteState) - useCadFile && (imgPath = `/cadImages/${cadFileName}`) - - // 구글맵 이미지 업로드 - const [useGoogleMapFile, setUseGoogleMapFile] = useRecoilState(useGoogleMapFileState) - const [googleMapFileName, setGoogleMapFileName] = useRecoilState(googleMapFileNameState) - useGoogleMapFile && (imgPath = `/mapImages/${googleMapFileName}`) - - const [globalCampass, setGlobalCampass] = useRecoilState(globalCompassState) - - const { - mode, - setMode, - changeMode, - handleClear, - zoomIn, - zoomOut, - zoom, - togglePolygonLine, - handleOuterlinesTest, - handleOuterlinesTest2, - applyTemplateB, - makeRoofPatternPolygon, - createRoofRack, - drawRoofPolygon, - drawCellInTrestle, - drawCellManualInTrestle, - setDirectionTrestles, - cutHelpLines, - } = useMode() - - // const [canvasState, setCanvasState] = useRecoilState(canvasAtom) - - useEffect(() => { - get({ url: `/api/canvas-management/canvas-statuses/by-object/test123240822001/${userId}` }).then((res) => { - // console.log(res) - - const arrangeData = res.map((item) => { - // console.log(item.canvasStatus.replace(/##/g, '"').replace(/\\/g, '')) - const test = item.canvasStatus.replace(/##/g, '"').replace(/\\/g, '') - const test2 = test.substring(1, test.length - 1) - return { - id: item.id, - userId: item.userId, - imageName: `/canvasState/${item.imageName}.png`, - canvasStatus: JSON.stringify(test2), - } - }) - setThumbnails(arrangeData) - }) - }, []) - - useEffect(() => { - if (!canvas) { - return - } - changeMode(canvas, mode) - - if (!cadFileComplete && useCadFile) { - // cad 파일 로드 - useCadFile && handleBackImageLoadToCanvas(imgPath, canvas) - } - - if (useGoogleMapFile) { - handleBackImageLoadToCanvas(imgPath, canvas) - } - }, [canvas, mode]) - - const makeLine = () => { - if (canvas) { - const line = new QLine([50, 50, 200, 50], { - stroke: 'black', - selectable: true, - strokeWidth: 2, - fontSize: fontSize, - }) - - canvas?.add(line) - } - } - - const makePolygon = () => { - if (canvas) { - const polygon = new QPolygon( - [ - { x: 100, y: 100 }, - { x: 600, y: 200 }, - { x: 700, y: 800 }, - { x: 100, y: 800 }, - ], - { - fill: 'transparent', - stroke: 'black', - strokeWidth: 2, - selectable: true, - fontSize: fontSize, - }, - ) - canvas?.add(polygon) - - // polygon.fillCell({ width: 50, height: 30, padding: 10 }) - } - } - - useEffect(() => { - setCanvasSize({ ...canvasSize, vertical: parseInt(verticalSize), horizontal: parseInt(horizontalSize) }) - }, [verticalSize, horizontalSize]) - - /** - * 값 변경시 - */ - // useEffect(() => { - // canvasSizeMode() - // }, [verticalSize, horizontalSize]) - useEffect(() => { - const { vertical, horizontal } = canvasSize - if (vertical !== verticalSize || horizontal !== horizontalSize) { - canvas?.setWidth(horizontalSize) - canvas?.setHeight(verticalSize) - canvas?.renderAll() - } - }, [canvasSize, canvas]) - - const makeQPolygon = () => { - const type1 = [ - { x: 100, y: 100 }, - { x: 850, y: 100 }, - { x: 850, y: 800 }, - { x: 500, y: 800 }, - { x: 500, y: 400 }, - { x: 100, y: 400 }, - ] - const type2 = [ - { x: 200, y: 100 }, - { x: 200, y: 1000 }, - { x: 1100, y: 1000 }, - { x: 1100, y: 600 }, - { x: 650, y: 600 }, - { x: 650, y: 100 }, - ] - - const type3 = [ - { x: 200, y: 100 }, - { x: 200, y: 800 }, - { x: 500, y: 800 }, - { x: 500, y: 300 }, - { x: 800, y: 300 }, - { x: 800, y: 100 }, - ] - - const type4 = [ - { x: 150, y: 450 }, - { x: 150, y: 800 }, - { x: 750, y: 800 }, - { x: 750, y: 300 }, - { x: 550, y: 300 }, - { x: 550, y: 450 }, - ] - - const type1A = [ - { x: 67, y: 81 }, - { x: 67, y: 660 }, - { x: 437, y: 660 }, - { x: 437, y: 1190 }, - { x: 858, y: 1190 }, - { x: 858, y: 81 }, - ] - - const type1B = [ - { x: 137, y: 42 }, - { x: 137, y: 621 }, - { x: 667, y: 621 }, - { x: 667, y: 991 }, - { x: 1088, y: 991 }, - { x: 1088, y: 42 }, - ] - - const eightPoint = [ - { x: 240.1111, y: 130.1111 }, - { x: 240.1111, y: 630.1111 }, - { x: 640.1111, y: 630.1111 }, - { x: 640.1111, y: 480.1111 }, - { x: 440.1111, y: 480.1111 }, - { x: 440.1111, y: 280.1111 }, - { x: 740.1111, y: 280.1111 }, - { x: 740.1111, y: 130.1111 }, - ] - - const eightPoint2 = [ - { x: 197, y: 215 }, - { x: 197, y: 815 }, - { x: 397, y: 815 }, - { x: 397, y: 1115 }, - { x: 697, y: 1115 }, - { x: 697, y: 815 }, - { x: 897, y: 815 }, - { x: 897, y: 215 }, - ] - - const eightPoint3 = [ - { x: 190, y: 147 }, - { x: 190, y: 747 }, - { x: 490, y: 747 }, - { x: 490, y: 497 }, - { x: 640, y: 497 }, - { x: 640, y: 747 }, - { x: 1090, y: 747 }, - { x: 1090, y: 147 }, - ] - - const eightPoint4 = [ - { x: 200, y: 200 }, - { x: 200, y: 400 }, - { x: 500, y: 400 }, - { x: 500, y: 700 }, - { x: 800, y: 700 }, - { x: 800, y: 400 }, - { x: 1100, y: 400 }, - { x: 1100, y: 200 }, - ] - - const eightPoint5 = [ - { x: 140, y: 101 }, - { x: 140, y: 601 }, - { x: 440, y: 601 }, - { x: 440, y: 801 }, - { x: 840, y: 801 }, - { x: 840, y: 601 }, - { x: 1140, y: 601 }, - { x: 1140, y: 101 }, - ] - - const twelvePoint = [ - { x: 195, y: 166 }, - { x: 195, y: 466 }, - { x: 395, y: 466 }, - { x: 395, y: 766 }, - { x: 545, y: 766 }, - { x: 545, y: 466 }, - { x: 695, y: 466 }, - { x: 695, y: 666 }, - { x: 845, y: 666 }, - { x: 845, y: 466 }, - { x: 995, y: 466 }, - { x: 995, y: 166 }, - ] - - const twelvePoint2 = [ - { x: 165, y: 81 }, - { x: 165, y: 1081 }, - { x: 465, y: 1081 }, - { x: 465, y: 781 }, - { x: 765, y: 781 }, - { x: 765, y: 1081 }, - { x: 1065, y: 1081 }, - { x: 1065, y: 581 }, - { x: 765, y: 581 }, - { x: 765, y: 281 }, - { x: 1065, y: 281 }, - { x: 1065, y: 81 }, - ] - - const complicatedType = [ - { x: 100, y: 100 }, - { x: 100, y: 1100 }, - { x: 400, y: 1100 }, - { x: 400, y: 800 }, - { x: 700, y: 800 }, - { x: 700, y: 1100 }, - { x: 1000, y: 1100 }, - { x: 1000, y: 600 }, - { x: 700, y: 600 }, - { x: 700, y: 300 }, - { x: 1000, y: 300 }, - { x: 1000, y: 100 }, - ] - - const testType = [ - { x: 500, y: 400 }, - { x: 650, y: 550 }, - { x: 575, y: 625 }, - { x: 325, y: 625 }, - { x: 100, y: 400 }, - ] - - const testType2 = [ - { x: 100, y: 400 }, - { x: 325, y: 625 }, - { x: 575, y: 625 }, - { x: 650, y: 550 }, - { x: 500, y: 400 }, - ] - - const triangleType = [ - { x: 100, y: 100 }, - { x: 100, y: 600 }, - { x: 600, y: 600 }, - { x: 600, y: 100 }, - ] - - const rectangleType1 = [ - { x: 500, y: 100 }, - { x: 500, y: 800 }, - { x: 900, y: 800 }, - { x: 900, y: 100 }, - ] - - const rectangleType2 = [ - { x: 100, y: 100 }, - { x: 100, y: 300 }, - { x: 600, y: 300 }, - { x: 600, y: 100 }, - ] - - const types = [type1, type2, type3, type4, type1A, type1B, eightPoint, eightPoint2, eightPoint3, eightPoint4, twelvePoint] - const newP = [ - { x: 450, y: 450 }, - { x: 650, y: 250 }, - { x: 675, y: 275 }, - { x: 450, y: 850 }, - ] - - const test1 = [ - { x: 381, y: 178 }, - { x: 381, y: 659.3 }, - { x: 773.3, y: 659.3 }, - { x: 773.3, y: 497.9 }, - { x: 1457, y: 497.9 }, - { x: 1457, y: 178 }, - ] - - const test2 = [ - { x: 113, y: 114.9 }, - { x: 113, y: 371.9 }, - { x: 762, y: 371.9 }, - { x: 762, y: 818.7 }, - { x: 1478.6, y: 818.7 }, - { x: 1478.6, y: 114.9 }, - ] - - const test3 = [ - { x: 100, y: 100 }, - { x: 100, y: 600 }, - { x: 600, y: 600 }, - { x: 600, y: 100 }, - { x: 500, y: 100 }, - { x: 500, y: 200 }, - { x: 200, y: 200 }, - { x: 200, y: 100 }, - ] - - const test4 = [ - { x: 100, y: 100 }, - { x: 100, y: 1000 }, - { x: 1100, y: 1000 }, - { x: 1100, y: 550 }, - { x: 500, y: 550 }, - { x: 500, y: 100 }, - ] - - const polygon = new QPolygon(test4, { - fill: 'transparent', - stroke: 'green', - strokeWidth: 1, - selectable: false, - fontSize: fontSize, - name: 'wall', - }) - - canvas?.add(polygon) - handleOuterlinesTest2(polygon, 50) - setTemplateType(1) - } - - const rotateShape = () => { - if (canvas) { - const activeObject = canvas?.getActiveObject() - - if (activeObject) { - activeObject.rotate(angle) - canvas?.renderAll() - } - } - } - - const makeQLine = () => { - if (canvas) { - const line = new QLine([50, 250, 900, 250], { - stroke: 'black', - strokeWidth: 5, - fontSize: fontSize, - selectable: true, - }) - - const line2 = new QLine([450, 450, 821, 78], { - stroke: 'black', - strokeWidth: 5, - fontSize: fontSize, - selectable: true, - }) - - canvas?.add(line) - canvas?.add(line2) - - const interSectionPoint = calculateIntersection(line, line2) - - if (interSectionPoint) { - const circle = new fabric.Circle({ - radius: 5, - fill: 'red', - left: interSectionPoint.x - 5, - top: interSectionPoint.y - 5, - }) - - canvas?.add(circle) - } - } - } - - const addBackgroundInPolygon = (polygon) => { - fabric.Image.fromURL('assets/img/check2.png', function (img) { - // 패턴 객체를 생성합니다. - const pattern = new fabric.Pattern({ - source: img.getElement(), - repeat: 'repeat', - }) - - polygon.fillBackground(pattern) - }) - } - - function PolygonToLine() { - const polygon = canvas?.getActiveObject() - - if (polygon.type !== 'QPolygon') { - return - } - - const lines = togglePolygonLine(polygon) - } - - /** - * canvas 내용 저장하기 - */ - const handleSaveCanvas = async () => { - // const jsonStr = JSON.stringify(canvas?.toDatalessJSON(['type', 'fontSize'])) - const jsonObj = JSON.stringify(canvas?.toDatalessJSON(['type', 'fontSize', 'lines'])) - console.log(jsonObj) - - const param = { - loginId: 'test', - canvas: jsonObj, - } - console.log(param) - - await insertCanvasState(param) - handleClear() - } - - const drawRoofMaterial = () => { - const { width, height, roofStyle } = roofMaterial - - const wallPolygon = canvas?.getObjects().find((obj) => obj.name === 'wall') - - wallPolygon.set('strokeDashArray', [10, 5, 2, 5]) - wallPolygon.set('stroke', 'blue') - wallPolygon.set('strokeWidth', 1) - - const roofs = canvas?.getObjects().filter((obj) => obj.name === 'roof') - - roofs.forEach((roof) => { - let maxLengthLine = roof.lines.reduce((acc, cur) => { - return acc.length > cur.length ? acc : cur - }) - - const roofRatio = window.devicePixelRatio || 1 - - // 패턴 소스를 위한 임시 캔버스 생성 - const patternSourceCanvas = document.createElement('canvas') - if (roofStyle === 1) { - if (maxLengthLine.direction === 'right' || maxLengthLine.direction === 'left') { - patternSourceCanvas.width = width * roofRatio - patternSourceCanvas.height = height * roofRatio - } else { - patternSourceCanvas.width = height * roofRatio - patternSourceCanvas.height = width * roofRatio - } - } else if (roofStyle === 2) { - if (maxLengthLine.direction === 'right' || maxLengthLine.direction === 'left') { - patternSourceCanvas.width = width * 2 - patternSourceCanvas.height = height * 2 - } else { - patternSourceCanvas.width = height * 2 - patternSourceCanvas.height = width * 2 - } - } - - const ctx = patternSourceCanvas.getContext('2d') - - ctx.scale(roofRatio, roofRatio) - ctx.strokeStyle = 'green' - ctx.lineWidth = 0.4 - // 벽돌 패턴 그리기 - if (roofStyle === 1) { - ctx.strokeRect(0, 0, 50, 30) - } else if (roofStyle === 2) { - // 지그재그 - ctx.strokeRect(0, 0, 200, 100) - ctx.strokeRect(100, 100, 200, 100) - } - - // 패턴 생성 - const pattern = new fabric.Pattern({ - source: patternSourceCanvas, - repeat: 'repeat', - }) - roof.set('fill', null) - - roof.set('fill', pattern) - canvas?.renderAll() - }) - } - - /** - * canvas 내용 불러오기 - */ - const handleLoadCanvas = async () => { - const canvasStates = await getCanvasState() - console.log(JSON.parse(canvasStates.canvas)) - canvas?.loadFromJSON(JSON.parse(canvasStates.canvas)) - } - - /** - * 컨트롤러 보이기/숨기기 - */ - const handleShowController = () => { - setShowControl(!showControl) - } - - const drawRoofPatterns = (roofStyle) => { - makeRoofPatternPolygon(roofStyle) - } - - const deleteCell = () => { - const selectedCells = canvas?.getObjects().filter((obj) => obj.name === 'cell' && obj.selected) - - selectedCells.forEach((cell) => { - canvas?.remove(cell) - }) - } - - const setCompassState = (degree) => { - setCompass(degree) - } - - const changeLength = (e) => { - const polygon = canvas?.getActiveObject() - - if (polygon?.type !== 'QPolygon') { - return - } - setScale(e) - polygon.setScaleX(e) - - canvas?.renderAll() - } - - const moduleConfiguration = () => { - createRoofRack() - } - - const setDirectionStringToArrow = () => { - drawDirectionStringToArrow(canvas, globalCampass) - - /** - * 나중에 유틸로 다시 구현 - */ - // const groupShapes = canvas?.getObjects().filter((obj) => obj.name === 'cellGroup') - - // console.log('groupShapes', groupShapes) - - // groupShapes.forEach((obj) => { - // let originAngle = obj._objects.find((array) => array.originAngle !== undefined).originAngle - - // console.log('originAngle', originAngle) - - // let rotateAngle = globalCampass - - // // let rotateAngle = originAngle + globalCampass - // // if (rotateAngle > 360) { - // // rotateAngle -= 360 - // // } - - // console.log('rotateAngle', rotateAngle) - - // obj.set({ angle: rotateAngle, originX: 'center', originY: 'center' }) - // obj.setCoords() - // }) - canvas?.renderAll() - } - - const setHipRoof = () => { - const polygon = canvas?.getObjects().find((obj) => obj.name === 'roof') - const currentRoof = polygon.lines[2] - currentRoof.attributes.type = LINE_TYPE.WALLLINE.EAVES - currentRoof.attributes.offset = 50 - changeCurrentRoof(currentRoof, canvas) - } - const setGableRoof = () => { - const polygon = canvas?.getObjects().find((obj) => obj.name === 'roof') - const currentRoof = polygon.lines[2] - currentRoof.attributes.type = LINE_TYPE.WALLLINE.GABLE - currentRoof.attributes.offset = 30 - changeCurrentRoof(currentRoof, canvas) - } - const setHipAndGableRoof = () => { - let offset = Number(prompt('팔작지붕 폭', '50')) - if (!isNaN(offset) && offset > 0) { - const polygon = canvas?.getObjects().find((obj) => obj.name === 'roof') - const currentRoof = polygon.lines[2] - currentRoof.attributes.type = LINE_TYPE.WALLLINE.HIPANDGABLE - currentRoof.attributes.width = offset - changeCurrentRoof(currentRoof, canvas) - } else { - alert('폭은 0 보다 커야 함') - } - } - const setJerkInHeadRoof = () => { - let offset = Number(prompt('팔작지붕 폭', '50')) - if (!isNaN(offset) && offset > 0) { - const polygon = canvas?.getObjects().find((obj) => obj.name === 'roof') - const currentRoof = polygon.lines[2] - currentRoof.attributes.type = LINE_TYPE.WALLLINE.JERKINHEAD - currentRoof.attributes.width = offset - changeCurrentRoof(currentRoof, canvas) - } else { - alert('폭은 0 보다 커야 함') - } - } - const setWallRoof = () => { - let offset = Number(prompt('소매 폭', '0')) - const polygon = canvas?.getObjects().find((obj) => obj.name === 'roof') - const currentRoof = polygon.lines[2] - currentRoof.attributes.type = LINE_TYPE.WALLLINE.WALL - currentRoof.attributes.width = offset - changeCurrentRoof(currentRoof, canvas) - } - return ( - <> - {canvas && ( - <> -
- - - - - - - - - - - - - - - - - - - - - - - - - - { - - } - - 현재 줌 : {zoom}% - - - {/*{templateType === 0 && (*/} - {/* <>*/} - - {/* */} - {/*)}*/} - - - - - - - - - {/**/} - {/* - - */} - - {templateType === 1 && ( - <> - - - - - - )} - - - - - - - -
-
-
- -
-
- -
-
- -
-
- -
-
- -
-
- - )} - - {/*
-

각도 입력(0~360) 후 방향설정 클릭

- { - const val = e.target.value.replace(/[^-0-9]/g, '') - if (val < 0 || val > 360) { - setGlobalCampass(0) - } else { - setGlobalCampass(Number(val)) - } - }} - /> - -
*/} - {/*
- Compass Circle -
- N, S, E, W Labels -
N
-
S
-
- E -
-
- W -
-
- - Compass Pointer -
- Red Upper Triangle -
-
-
*/} -
- - {!canvas ? null : mode === Mode.DRAW_LINE ? ( - - ) : currentObject?.type === 'QPolygon' ? ( - - ) : currentObject?.type === 'QLine' ? ( - - ) : ( - - )} -
- - ) -} diff --git a/src/components/Settings.jsx b/src/components/Settings.jsx deleted file mode 100644 index 51680711..00000000 --- a/src/components/Settings.jsx +++ /dev/null @@ -1,324 +0,0 @@ -'use client' - -import React, { useEffect, useState } from 'react' -import { Button } from '@nextui-org/react' - -import { useAxios } from '@/hooks/useAxios' - -import { useRecoilState } from 'recoil' -import { customSettingsState } from '@/store/canvasAtom' -import { modalContent, modalState } from '@/store/modalAtom' - -import ColorPicker from './common/color-picker/ColorPicker' - -export default function Settings() { - const [objectNo, setObjectNo] = useState('test123240829010') - const [error, setError] = useState(null) - const [customSettings, setCustomSettings] = useRecoilState(customSettingsState) - - const [color, setColor] = useState('#ff0000') - - const [open, setOpen] = useRecoilState(modalState) - const [contents, setContent] = useRecoilState(modalContent) - - const { get, post } = useAxios() - - const handleSavePopup = () => { - console.log('color ', color) - } - - const handleClosePopup = () => { - setContent('') - setOpen(false) - console.log('colorSetting ', color) - } - - const colorSetting = ( - <> -
-

React ColorPicker

- -
{color}
-
-

- -

- - ) - - const customStyles = { - overlay: { - backgroundColor: 'rgba(0,0,0,0.5)', - }, - content: { - width: '300px', - height: '400px', - margin: 'auto', - borderRadius: '4px', - boxShadow: '0 2px 4px rgba(0,0,0,0.2)', - padding: '20px', - }, - } - - // 상태를 하나의 객체로 관리 - const [settings, setSettings] = useState({ - display1: Array(11).fill(false), // 화면 표시1 - display2: Array(3).fill(false), // 화면 표시2 - rangeSetting: 0, // 흡착 범위 설정 - gridSettings: Array(5).fill(false), // 그리드 설정 - }) - - const gridItems = { - display1: [ - '할당 표시', - '도면 표시', - '그리드 표시', - '문자 표시', - '흐름방향 표시', - '복도치수 표시', - '실제치수 표시', - '치수 표시 없음', - '가대 표시', - '좌표 표시', - '도면전환 표시', - ], - display2: ['테두리만', '라인해치', 'All Painted'], - rangeSetting: ['극소', '소', '중', '대'], - gridSettings: ['임의 그리드', '실선 그리드', '점 그리드', '그리드 색 설정', '흡착점 추가'], - } - - // 초기 조회 - useEffect(() => { - if (!objectNo) { - alert('object_no를 입력하세요.') - } - }, []) - - // 클릭 시 상태 변경 함수 - const handleToggle = (type, index) => { - // '실선 그리드' 클릭 시 팝업 열기 - if (type === 'gridSettings' && gridItems.gridSettings[index] === '실선 그리드') { - //openGridPopup() - } - - // '그리드 색 설정' 클릭 시 팝업 열기 - if (type === 'gridSettings' && gridItems.gridSettings[index] === '그리드 색 설정') { - //setSelectedGridSetting(gridItems.gridSettings[index]) - //setIsPopupOpen(true) - //return prevSettings // 설정은 변경하지 않음 - - setOpen(true) - setContent({ ...colorSetting }) - } - - setSettings((prevSettings) => { - // prevSettings[type]이 배열인지 확인하고, 그렇지 않은 경우 빈 배열로 초기화 - let updated = Array.isArray(prevSettings[type]) ? [...prevSettings[type]] : [] - - if (type === 'rangeSetting') { - return { ...prevSettings, [type]: index } - } - - updated[index] = updated[index] === false ? true : false - return { ...prevSettings, [type]: updated } - }) - } - - // '실선 그리드' 클릭 시 팝업을 열기 위한 함수 - const openGridPopup = () => { - const popupWidth = 500 - const popupHeight = 300 - - // 팝업 창 위치를 화면 중앙으로 조정하기 위해 계산 - const left = window.innerWidth / 2 - popupWidth / 2 - const top = window.innerHeight / 2 - popupHeight / 2 - - // 새 창 열기 - window - .open - //'./components/intro', // 팝업으로 띄울 페이지의 URL - //'_blank', // 새 창으로 열기 - //`width=${popupWidth},height=${popupHeight},top=${top},left=${left}`, // 크기와 위치 지정 - () - } - - // Canvas Setting 조회 및 초기화 - const handleSelect = async () => { - try { - if (!objectNo) { - alert('object_no를 입력하세요.') - return - } - - const res = await get({ url: `/api/canvas-management/canvas-settings/by-object/${objectNo}` }) - - // 데이터가 없는 경우 - if (!res) { - console.warn('조회 결과가 없습니다.') - // 기본값을 설정하거나 사용자에게 알림 표시 - setSettings({ - display1: Array(11).fill(false), // 화면 표시1 기본값 - display2: Array(3).fill(false), // 화면 표시2 기본값 - rangeSetting: 0, // 흡착 범위 설정 기본값 - gridSettings: Array(5).fill(false), // 그리드 설정 기본값 - }) - - alert('조회된 데이터가 없습니다. 기본 설정이 적용됩니다.') - return // 이후 코드 실행을 중단 - } - - const data = { - display1: [ - res.assignDisplay, - res.drawDisplay, - res.gridDisplay, - res.charDisplay, - res.flowDisplay, - res.hallwayDimenDisplay, - res.actualDimenDisplay, - res.noDimenDisplay, - res.trestleDisplay, - res.coordiDisplay, - res.drawConverDisplay, - ], - display2: [res.onlyBorder, res.lineHatch, res.allPainted], - rangeSetting: res.adsorpRangeSetting, - gridSettings: [res.randomGrid, res.solidGrid, res.dotGrid, res.gridColorSet, res.adsorpPointAdd], - } - - // 데이터 설정 - setSettings({ - display1: data.display1, - display2: data.display2, - rangeSetting: data.rangeSetting, - gridSettings: data.gridSettings, - }) - } catch (error) { - console.error('Data fetching error:', error) - } - } - - // Canvas Setting 저장 - const handleSubmit = async () => { - if (!objectNo) { - alert('object_no를 입력하세요.') - return - } - - const patternData = { - objectNo, - assignDisplay: settings.display1[0], - drawDisplay: settings.display1[1], - gridDisplay: settings.display1[2], - charDisplay: settings.display1[3], - flowDisplay: settings.display1[4], - hallwayDimenDisplay: settings.display1[5], - actualDimenDisplay: settings.display1[6], - noDimenDisplay: settings.display1[7], - trestleDisplay: settings.display1[8], - coordiDisplay: settings.display1[9], - drawConverDisplay: settings.display1[10], - onlyBorder: settings.display2[0], - lineHatch: settings.display2[1], - allPainted: settings.display2[2], - adsorpRangeSetting: settings.rangeSetting, - randomGrid: settings.gridSettings[0], - solidGrid: settings.gridSettings[1], - dotGrid: settings.gridSettings[2], - gridColorSet: settings.gridSettings[3], - adsorpPointAdd: settings.gridSettings[4], - } - - console.log('patternData', patternData) - - await post({ url: `/api/canvas-management/canvas-settings`, data: patternData }) - - //Recoil 설정 - setCustomSettings({ ...patternData }) - - // 저장 후 재조회 - await handleSelect() - } - - return ( - <> -
-
- setObjectNo(e.target.value)} /> - - -
-
-

[디스플레이 설정]

-

* 도면에 표시할 항목을 클릭하면 적용 됩니다.

-
- {gridItems.display1.map((item, index) => ( -
handleToggle('display1', index)} - > - {settings.display1[index]} {item} -
- ))} -
-
-

* 화면 표시

-
- {gridItems.display2.map((item, index) => ( -
handleToggle('display2', index)} - > - {settings.display2[index]} {item} -
- ))} -
-

[글꼴/도면크기 설정]

-

* 글꼴 및 크기 변경

-
-
문자 글꼴 변경
-
흐름방향 글꼴 변경
-
치수 글꼴 변경
-
회로번호 글꼴 변경
-
- `` -

* 흡착 범위 설정

-
- {gridItems.rangeSetting.map((item, index) => ( -
handleToggle('rangeSetting', index)} - > - {item} -
- ))} -
-
-
치수선 설정
-
도면 크기 설정
-
흡착점 ON
-
-

[그리드 설정]

-
- -
{color}
-
-
- {gridItems.gridSettings.map((item, index) => ( -
handleToggle('gridSettings', index)} - > - {settings.gridSettings[index]} {item} -
- ))} -
-
-
- - ) -} diff --git a/src/components/auth/Login.jsx b/src/components/auth/Login.jsx index b23f9c53..85e342d4 100644 --- a/src/components/auth/Login.jsx +++ b/src/components/auth/Login.jsx @@ -9,7 +9,7 @@ import { setSession, login, checkSession } from '@/lib/authActions' import { useMessage } from '@/hooks/useMessage' import { globalLocaleStore } from '@/store/localeAtom' import { sessionStore } from '@/store/commonAtom' -import { useRouter } from 'next/navigation' +import { redirect, useRouter } from 'next/navigation' import { useSearchParams } from 'next/navigation' import GlobalSpinner from '@/components/common/spinner/GlobalSpinner' @@ -28,11 +28,13 @@ export default function Login() { autoLoginProcess(autoLoginParam) } - checkSession().then((res) => { - if (res) { - login() - } - }) + // console.log('🚀 ~ checkSession ~ checkSession():', checkSession()) + // checkSession().then((res) => { + // console.log('🚀 ~ checkSession ~ res:', res) + // if (res) { + // login() + // } + // }) }, []) const autoLoginProcess = async (autoLoginParam) => { @@ -49,7 +51,7 @@ export default function Login() { setSessionState(result) login() } else { - router.push('/login') + router.push('/login', undefined, { shallow: true }) } }) } diff --git a/src/components/common/color-picker/ColorPickerModal.jsx b/src/components/common/color-picker/ColorPickerModal.jsx index 0f3b1b99..f6176bdb 100644 --- a/src/components/common/color-picker/ColorPickerModal.jsx +++ b/src/components/common/color-picker/ColorPickerModal.jsx @@ -33,53 +33,43 @@ export default function ColorPickerModal(props) { }, [isShow]) return ( - -
-
-

{getMessage('modal.color.picker.title')}

+ + { + if (setIsShow) { + setIsShow(false) + } + closePopup(id, isConfig) + }} + /> + +
+
+ +
+
+
-
-
-
COLOR PICKER
-
- -
-
-
- -
-
-
-
+ ) } diff --git a/src/components/common/context-menu/QContextMenu.jsx b/src/components/common/context-menu/QContextMenu.jsx index 63160eda..cd8b9e2b 100644 --- a/src/components/common/context-menu/QContextMenu.jsx +++ b/src/components/common/context-menu/QContextMenu.jsx @@ -40,7 +40,7 @@ export default function QContextMenu(props) { if (!contextRef.current) return const handleContextMenu = (e) => { - // e.preventDefault() //기존 contextmenu 막고 + e.preventDefault() //기존 contextmenu 막고 if (tempGridMode) return const position = { x: window.innerWidth / 2 < e.pageX ? e.pageX - 240 : e.pageX, @@ -113,7 +113,7 @@ export default function QContextMenu(props) { return ( <> {contextMenu.visible && ( -
+
{/*
    */} {/*
  • handleObjectMove()}>*/} {/* 이동*/} diff --git a/src/components/common/draggable/WithDraggable.jsx b/src/components/common/draggable/WithDraggable.jsx index 732d8ff7..9a51358c 100644 --- a/src/components/common/draggable/WithDraggable.jsx +++ b/src/components/common/draggable/WithDraggable.jsx @@ -2,9 +2,13 @@ import { useState } from 'react' import Draggable from 'react-draggable' +import PopSpinner from '../spinner/PopSpinner' +import { popSpinnerState } from '@/store/popupAtom' +import { useRecoilState } from 'recoil' -export default function WithDraggable({ isShow, children, pos = { x: 0, y: 0 }, handle = '' }) { +export default function WithDraggable({ isShow, children, pos = { x: 0, y: 0 }, handle = '', className = '', hasFooter = true, isHidden = false }) { const [position, setPosition] = useState(pos) + const [popSpinnerStore, setPopSpinnerStore] = useRecoilState(popSpinnerState) const handleOnDrag = (e, data) => { e.stopPropagation() @@ -22,9 +26,44 @@ export default function WithDraggable({ isShow, children, pos = { x: 0, y: 0 }, onDrag={(e, data) => handleOnDrag(e, data)} handle={handle === '' ? '.modal-handle' : handle} > - {children} +
    + {children} + {hasFooter && } + {popSpinnerStore && } +
    )} ) } + +function WithDraggableHeader({ title, onClose, children }) { + return ( +
    +

    {title}

    + {onClose && ( + + )} +
    + ) +} + +function WithDraggableBody({ children }) { + return ( +
    +
    +
    + <>{children} +
    + ) +} + +function WithDraggableFooter() { + return
    +} + +WithDraggable.Header = WithDraggableHeader +WithDraggable.Body = WithDraggableBody +WithDraggable.Footer = WithDraggableFooter diff --git a/src/components/common/font/FontSetting.jsx b/src/components/common/font/FontSetting.jsx index ddddefca..0c3623f6 100644 --- a/src/components/common/font/FontSetting.jsx +++ b/src/components/common/font/FontSetting.jsx @@ -67,109 +67,101 @@ export default function FontSetting(props) { } return ( - -
    -
    -

    {getMessage('modal.font')}

    -
    -
    -
    -
    -
    -
    {getMessage('modal.font')}(F)
    -
    - { - setSelectedFont(e) - }} - showKey={'name'} - sourceKey={'value'} - targetKey={'value'} - /> -
    -
    -
    -
    {getMessage('modal.font.style')}(Y)
    -
    - { - setSelectedFontWeight(e) - }} - showKey={'name'} - targetKey={'id'} - sourceKey={'id'} - /> -
    -
    -
    -
    {getMessage('modal.font.size')}(S)
    -
    - setSelectedFontSize(e)} - showKey={'name'} - sourceKey={'value'} - targetKey={'value'} - /> -
    -
    -
    -
    {getMessage('modal.font.color')}
    -
    - { - setSelectedFontColor(e) - }} - /> -
    -
    -
    -
    -
    {getMessage('modal.font.setting.display')}
    -
    - - Aaあぁアァ - -
    -
    -
    {getMessage('modal.font.setting.info')}
    -
    -
    - -
    -
    -
    -
    +
    ) } diff --git a/src/components/common/pagination/QPagination.jsx b/src/components/common/pagination/QPagination.jsx index c6cab52d..3b0fe205 100644 --- a/src/components/common/pagination/QPagination.jsx +++ b/src/components/common/pagination/QPagination.jsx @@ -12,10 +12,12 @@ export default function QPagination(props) { return (
    1. - +
    2. {pageRange.map((page) => (
    3. - +
    4. ))}
    5. - +
    ) diff --git a/src/components/common/spinner/GlobalSpinner.jsx b/src/components/common/spinner/GlobalSpinner.jsx index 1da91ef9..458bcabb 100644 --- a/src/components/common/spinner/GlobalSpinner.jsx +++ b/src/components/common/spinner/GlobalSpinner.jsx @@ -2,6 +2,11 @@ import '@/styles/spinner.scss' +/** + * 전역 스피너 + * 전역 로딩 스피너 + * @returns + */ export default function GlobalSpinner() { return ( <> diff --git a/src/components/common/spinner/PopSpinner.jsx b/src/components/common/spinner/PopSpinner.jsx new file mode 100644 index 00000000..56b54b76 --- /dev/null +++ b/src/components/common/spinner/PopSpinner.jsx @@ -0,0 +1,7 @@ +export default function PopSpinner() { + return ( +
    + +
    + ) +} diff --git a/src/components/estimate/Estimate.jsx b/src/components/estimate/Estimate.jsx index be1ea754..a44af878 100644 --- a/src/components/estimate/Estimate.jsx +++ b/src/components/estimate/Estimate.jsx @@ -1,10 +1,9 @@ 'use client' import { useEffect, useState, useContext } from 'react' -import { useRecoilValue, useSetRecoilState } from 'recoil' +import { useRecoilValue } from 'recoil' import { floorPlanObjectState } from '@/store/floorPlanObjectAtom' import { useMessage } from '@/hooks/useMessage' -import { useCanvasMenu } from '@/hooks/common/useCanvasMenu' import SingleDatePicker from '../common/datepicker/SingleDatePicker' import EstimateFileUploader from './EstimateFileUploader' import { useAxios } from '@/hooks/useAxios' @@ -14,17 +13,16 @@ import dayjs from 'dayjs' import { useCommonCode } from '@/hooks/common/useCommonCode' import { useEstimateController } from '@/hooks/floorPlan/estimate/useEstimateController' import { SessionContext } from '@/app/SessionProvider' -import Select, { components } from 'react-select' +import Select from 'react-select' import { convertNumberToPriceDecimal, convertNumberToPriceDecimalToFixed } from '@/util/common-utils' import ProductFeaturesPop from './popup/ProductFeaturesPop' import { v4 as uuidv4 } from 'uuid' -import { correntObjectNoState } from '@/store/settingAtom' import { useSearchParams } from 'next/navigation' import { usePlan } from '@/hooks/usePlan' import { usePopup } from '@/hooks/usePopup' import { useSwal } from '@/hooks/useSwal' import { QcastContext } from '@/app/QcastProvider' - +import { useCanvasMenu } from '@/hooks/common/useCanvasMenu' export default function Estimate({}) { const [uniqueData, setUniqueData] = useState([]) const [handlePricingFlag, setHandlePricingFlag] = useState(false) @@ -48,10 +46,10 @@ export default function Estimate({}) { const [selection, setSelection] = useState(new Set()) //견적특이사항 접고 펼치기 - // const [hidden, setHidden] = useState(false) const [hidden, setHidden] = useState(true) //아이템 자동완성 리스트 + const [originDisplayItemList, setOriginDisplayItemList] = useState([]) const [displayItemList, setDisplayItemList] = useState([]) //공통코드 @@ -60,6 +58,9 @@ export default function Estimate({}) { const [storePriceList, setStorePriceList] = useState([]) //가격표시 option + const [cableItemList, setCableItemList] = useState([]) //케이블 리스트 + const [cableItem, setCableItem] = useState('') //케이블 선택값 + const [startDate, setStartDate] = useState(new Date()) const singleDatePickerProps = { startDate, @@ -69,9 +70,9 @@ export default function Estimate({}) { * objectNo 셋팅 * url로 넘어온 objectNo을 리코일에 세팅 */ - const setCurrentObjectNo = useSetRecoilState(correntObjectNoState) const searchParams = useSearchParams() const objectRecoil = useRecoilValue(floorPlanObjectState) + const currentObjectNo = searchParams.get('objectNo') const currentPid = searchParams.get('pid') //견적서 상세데이터 const { estimateContextState, setEstimateContextState, addItem, handleEstimateFileDownload } = useEstimateController(currentPid, false) @@ -88,13 +89,8 @@ export default function Estimate({}) { const { getMessage } = useMessage() - const { setMenuNumber } = useCanvasMenu() - const { closeAll } = usePopup() - - const currentObjectNo = searchParams.get('objectNo') - setCurrentObjectNo(currentObjectNo) - + const { setSelectedMenu } = useCanvasMenu() //새로 추가한 첨부파일 props const fileUploadProps = { uploadFiles: files, @@ -104,8 +100,6 @@ export default function Estimate({}) { const initEstimate = (currPid = currentPid) => { console.log('🚀 ~ initEstimate ~ currPid:', currPid) closeAll() - setMenuNumber(5) - setObjectNo(objectRecoil.floorPlanObjectNo) setPlanNo(currPid) @@ -116,6 +110,16 @@ export default function Estimate({}) { setHonorificCodeList(code1) } + // 케이블제품 공통코드 + const code2 = findCommonCode(117900) + if (code2 != null) { + code2.map((item) => { + item.value = item.clRefChr1 + item.label = item.clRefChr2 + }) + setCableItemList(code2) + } + //아이템 자동완성 목록 가져오기 const param = { saleStoreId: session.storeId, @@ -123,7 +127,17 @@ export default function Estimate({}) { const apiUrl = `/api/display-item/item-list?${queryStringFormatter(param)}` post({ url: apiUrl, data: param }).then((res) => { if (res.length > 0) { - setDisplayItemList(res) + let tempList = [] + let updatedRes = [] + if (estimateContextState?.itemList.length > 0) { + tempList = estimateContextState.itemList.filter((item) => !res.some((resItem) => resItem.itemId === item.itemId)) + updatedRes = [...res, ...tempList] + } else { + updatedRes = [...res] + } + + setOriginDisplayItemList(res) + setDisplayItemList(updatedRes) } }) //견적특이사항 API호출 @@ -143,6 +157,7 @@ export default function Estimate({}) { }, [selectedPlan]) useEffect(() => { + setSelectedMenu('estimate') initEstimate() }, []) @@ -465,10 +480,6 @@ export default function Estimate({}) { //Pricing 버튼 const handlePricing = async (showPriceCd) => { - //todo: 추후 YJSS가 다시 나타날 경우 아래 swalFire 제거 필요 - if (estimateContextState.estimateType === 'YJSS') { - return swalFire({ text: getMessage('estimate.detail.save.requiredEstimateType'), type: 'alert', icon: 'warning' }) - } const param = { saleStoreId: session.storeId, sapSalesStoreCd: session.custCd, @@ -549,7 +560,7 @@ export default function Estimate({}) { } const getAbledItems = (items) => { - return items.filter((items) => items.paDispOrder === null) + return items.filter((items) => items.dispCableFlg !== '1' && items.paDispOrder === null) } const onChangeSelectAll = (e) => { @@ -566,7 +577,7 @@ export default function Estimate({}) { return selection.size === getAbledItems(estimateContextState.itemList).length } - //row 체크박스 컨트롤 + //아이템row 체크박스 컨트롤 const onChangeSelect = (dispOrder) => { const newSelection = new Set(selection) if (newSelection.has(dispOrder)) { @@ -578,10 +589,6 @@ export default function Estimate({}) { setSelection(newSelection) } - function formatNumberWithComma(number) { - return number.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',') - } - //주택PKG input 변경 const onChangePkgAsp = (value) => { if (estimateContextState.estimateType === 'YJSS') { @@ -686,12 +693,20 @@ export default function Estimate({}) { setItemChangeYn(true) } + /* 케이블 select 변경시 */ + const onChangeDisplayCableItem = (value, itemList) => { + itemList.map((item, index) => { + if (item.dispCableFlg === '1') { + if (value !== '') { + onChangeDisplayItem(value, item.dispOrder, index, true) + } + } + }) + setCableItem(value) + } + // 아이템 자동완성 검색시 아이템 추가/변경시 - const onChangeDisplayItem = (itemId, dispOrder, index) => { - //todo: 추후 YJSS가 다시 나타날 경우 아래 swalFire 제거 필요 - if (estimateContextState.estimateType === 'YJSS') { - return swalFire({ text: getMessage('estimate.detail.save.requiredEstimateType'), type: 'alert', icon: 'warning' }) - } + const onChangeDisplayItem = (itemId, dispOrder, index, flag) => { const param = { itemId: itemId, coldZoneFlg: estimateContextState?.coldRegionFlg, @@ -721,7 +736,7 @@ export default function Estimate({}) { updates.itemGroup = res.itemGroup updates.delFlg = '0' // 삭제플래그 0 updates.saleTotPrice = (res.salePrice * estimateContextState.itemList[index].amount).toString() - updates.amount = '' + updates.amount = flag ? estimateContextState.itemList[index].amount : '' updates.openFlg = res.openFlg if (estimateContextState.estimateType === 'YJSS') { @@ -784,6 +799,7 @@ export default function Estimate({}) { bomItem.objectNo = objectNo bomItem.planNo = planNo bomItem.addFlg = true //봄 추가시도 addFlg + bomItem.openFlg = '0' //봄 컴포넌트는 무조건 0으로 }) updateList = updateList.filter((item) => item.delFlg === '0') @@ -1002,7 +1018,7 @@ export default function Estimate({}) { item.showSaleTotPrice = '0' } }) - + let dispCableFlgCnt = 0 estimateContextState.itemList.forEach((item) => { if (item.delFlg === '0') { let amount = Number(item.amount?.replace(/[^0-9]/g, '').replaceAll(',', '')) || 0 @@ -1037,8 +1053,18 @@ export default function Estimate({}) { item.showSalePrice = '0' item.showSaleTotPrice = '0' } + + if (item.dispCableFlg === '1') { + dispCableFlgCnt++ + setCableItem(item.itemId) + } } }) + + if (dispCableFlgCnt === 0) { + setCableItem('100038') + } + let pkgAsp = estimateContextState.pkgAsp ? Number(estimateContextState.pkgAsp.replaceAll(',', '')) : 0 totals.pkgTotPrice = pkgAsp * totals.totVolKw * 1000 @@ -1066,6 +1092,7 @@ export default function Estimate({}) { } }) + let dispCableFlgCnt = 0 estimateContextState.itemList.forEach((item) => { delete item.showSalePrice delete item.showSaleTotPrice @@ -1093,9 +1120,21 @@ export default function Estimate({}) { item.showSalePrice = '0' item.showSaleTotPrice = '0' } + + if (item.dispCableFlg === '1') { + dispCableFlgCnt++ + } + + if (item.dispCableFlg === '1') { + setCableItem(item.itemId) + } } }) + if (dispCableFlgCnt === 0) { + setCableItem('100038') + } + totals.vatPrice = totals.supplyPrice * 0.1 totals.totPrice = totals.supplyPrice + totals.vatPrice @@ -1129,6 +1168,35 @@ export default function Estimate({}) { setSpecialNoteFirstFlg(false) }, [estimateContextState.resetFlag]) + useEffect(() => { + if (estimateContextState?.itemList.length > 0) { + const tempList = estimateContextState.itemList.filter((item) => !displayItemList.some((resItem) => resItem.itemId === item.itemId)) + if (tempList.length > 0) { + setDisplayItemList((prevList) => [...prevList, ...tempList]) + } + } + }, [estimateContextState]) + + useEffect(() => { + if (cableItemList.lenght > 0 || estimateContextState?.itemList.length > 0) { + let dispCableFlgCnt = 0 + estimateContextState.itemList.map((item) => { + if (item.dispCableFlg === '1') { + dispCableFlgCnt++ + cableItemList.map((cable) => { + if (item.itemId === cable.clRefChr1) { + cable.clRefChr3 = item.itemName + } + }) + } + }) + + if (dispCableFlgCnt === 0) { + setCableItem('100038') + } + } + }, [estimateContextState?.itemList, cableItemList]) + return (
    @@ -1139,7 +1207,6 @@ export default function Estimate({}) {
    {getMessage('estimate.detail.objectNo')}
    - {/* {objectNo} (Plan No: {estimateContextState.planNo}) */} {currentObjectNo} (Plan No: {planNo})
    @@ -1253,7 +1320,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 @@ -1275,7 +1342,7 @@ export default function Estimate({}) {
    - {/*
    +
    -
    */} +
    { - //todo: 추후 YJSS가 다시 나타날 경우 아래 주석풀기 - // setHandlePricingFlag(true) + setHandlePricingFlag(true) setEstimateContextState({ estimateType: e.target.value }) }} /> @@ -1568,9 +1634,7 @@ export default function Estimate({}) { {/* 견적특이사항 선택한 내용 영역끝 */}
    - {/* 견적 특이사항 코드영역 끝 */} - {/* 견적특이사항 영역끝 */} {/* 제품정보 시작 */}
    @@ -1580,10 +1644,6 @@ export default function Estimate({}) {
    - {/*
    -
    {getMessage('estimate.detail.sepcialEstimateProductInfo.totAmount')}
    -
    {convertNumberToPriceDecimal(estimateContextState?.totAmount)}
    -
    */}
    {getMessage('estimate.detail.sepcialEstimateProductInfo.totVolKw')}
    {convertNumberToPriceDecimalToFixed(estimateContextState?.totVolKw, 2)}
    @@ -1603,7 +1663,7 @@ export default function Estimate({}) {
    {/* YJOD면 아래영역 숨김 */} - {/*
    +
    @@ -1638,7 +1698,7 @@ export default function Estimate({}) {
    -
    */} +
    {/* 제품정보 끝 */} {/* 가격표시영역시작 */}
    @@ -1677,6 +1737,24 @@ export default function Estimate({}) { {getMessage('estimate.detail.showPrice.pricingBtn')}
    +
    +
    + +
    +
    • @@ -1720,7 +1798,7 @@ export default function Estimate({}) { - + @@ -1756,7 +1834,7 @@ export default function Estimate({}) { onChangeSelect(item.dispOrder)} checked={!!selection.has(item.dispOrder)} /> @@ -1767,27 +1845,50 @@ export default function Estimate({}) {
      - { + if (isObjectNotEmpty(e)) { + onChangeDisplayItem(e.itemId, item.dispOrder, index, false) + } + }} + menuPlacement={'auto'} + getOptionLabel={(x) => x.itemName} + getOptionValue={(x) => x.itemNo} + isClearable={false} + isDisabled={!!item?.paDispOrder} + value={displayItemList.filter(function (option) { + if (item.itemNo === '') { + return false + } else { + return option.itemId === item.itemId + } + })} + /> + ) : ( +
    - {/* html테이블끝 */}
    diff --git a/src/components/estimate/EstimateFileUploader.jsx b/src/components/estimate/EstimateFileUploader.jsx index 950ed6af..b02daef1 100644 --- a/src/components/estimate/EstimateFileUploader.jsx +++ b/src/components/estimate/EstimateFileUploader.jsx @@ -3,11 +3,14 @@ import { useRef } from 'react' import { v4 as uuidv4 } from 'uuid' import { useMessage } from '@/hooks/useMessage' +import { useSwal } from '@/hooks/useSwal' export default function EstimateFileUploader({ uploadFiles, setUploadFiles }) { const fileInputRef = useRef(null) const { getMessage } = useMessage() + const { swalFire } = useSwal() + const handleButtonClick = (e) => { e.preventDefault() fileInputRef.current.click() @@ -20,9 +23,18 @@ export default function EstimateFileUploader({ uploadFiles, setUploadFiles }) { const fileList = [] let passFlag = true + const allowedFileTypes = [ + 'image/', + '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) => { - let fileType = file.type - if (!fileType.includes('image')) { + //엑셀, pdf, 이미지 + const fileType = file.type + if (!allowedFileTypes.some((type) => fileType.includes(type))) { passFlag = false } else { fileList.push({ data: file, id: uuidv4() }) @@ -30,30 +42,11 @@ export default function EstimateFileUploader({ uploadFiles, setUploadFiles }) { }) if (!passFlag) { - alert(getMessage('estimate.detail.fileList.extCheck')) + swalFire({ text: getMessage('estimate.detail.fileList.extCheck'), type: 'alert', icon: 'error' }) } - // const { files } = e.target - // const file = files[0] - // const fileType = file.type - // if (!fileType.includes('image')) { - // return alert(getMessage('estimate.detail.fileList.extCheck')) - // } - - // setUploadFiles([...uploadFiles, { data: e.target.files[0], id: uuidv4() }]) - //다중으로 변경 setUploadFiles([...uploadFiles, ...fileList]) e.target.value = '' - // const formData = new FormData() - // formData.append('file', e.target.files[0]) - // formData.append('objectNo', objectNo) // 받아와야 하는 값 - // formData.append('planNo', planNo) // 받아와야 하는 값 - // formData.append('category', category) // 받아와야 하는 값 - // formData.append('userId', session.userId) - - // await promisePost({ url: '/api/file/fileUpload', data: formData }).then((res) => { - // if (res.data > 0) setUploadFiles([...files, { name: e.target.files[0].name, id: uuidv4() }]) - // }) } const deleteFile = (id) => { @@ -65,10 +58,19 @@ export default function EstimateFileUploader({ uploadFiles, setUploadFiles }) { e.stopPropagation() const fileList = [] let passFlag = true + const allowedFileTypes = [ + 'image/', + '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) => { + //엑셀, pdf, 이미지 let fileType = file.type - if (!fileType.includes('image')) { + if (!allowedFileTypes.some((type) => fileType.includes(type))) { passFlag = false } else { fileList.push({ data: file, id: uuidv4() }) @@ -76,7 +78,7 @@ export default function EstimateFileUploader({ uploadFiles, setUploadFiles }) { }) if (!passFlag) { - alert(getMessage('estimate.detail.fileList.extCheck')) + swalFire({ text: getMessage('estimate.detail.fileList.extCheck'), type: 'alert', icon: 'error' }) } setUploadFiles([...uploadFiles, ...fileList]) @@ -103,16 +105,7 @@ export default function EstimateFileUploader({ uploadFiles, setUploadFiles }) { - onChangeFiles(e)} - /> + onChangeFiles(e)} />
    { + setIsGlobalLoading(false) if (resultData) { let fileName = 'unknow' const blob = new Blob([resultData.data], { type: resultData.headers['content-type'] || 'application/octet-stream' }) @@ -97,6 +102,7 @@ export default function DocDownOptionPop({ planNo, setEstimatePopupOpen, docDown } }) .catch((error) => { + setIsGlobalLoading(false) console.log('::FileDownLoad Error::', error) alert('File does not exist.') }) diff --git a/src/components/estimate/popup/EstimateCopyPop.jsx b/src/components/estimate/popup/EstimateCopyPop.jsx index 6ff2e540..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]) @@ -296,7 +296,7 @@ export default function EstimateCopyPop({ planNo, setEstimateCopyPopupOpen }) { type="button" className="btn-origin navy mr5" onClick={() => { - handleEstimateCopy(sendPlanNo, copyReceiveUser, saleStoreId, otherSaleStoreId) + handleEstimateCopy(sendPlanNo, copyReceiveUser, saleStoreId, otherSaleStoreId, setEstimateCopyPopupOpen) }} > {getMessage('estimate.detail.estimateCopyPopup.copyBtn')} diff --git a/src/components/fabric/QLine.js b/src/components/fabric/QLine.js index 7fc1afc1..9c9791c9 100644 --- a/src/components/fabric/QLine.js +++ b/src/components/fabric/QLine.js @@ -13,6 +13,7 @@ export const QLine = fabric.util.createClass(fabric.Line, { area: 0, children: [], padding: 5, + textVisible: true, initialize: function (points, options, length = 0) { // 소수점 전부 제거 @@ -29,6 +30,7 @@ export const QLine = fabric.util.createClass(fabric.Line, { this.idx = options.idx ?? 0 this.direction = options.direction ?? getDirectionByPoint({ x: this.x1, y: this.y1 }, { x: this.x2, y: this.y2 }) this.textMode = options.textMode ?? 'plane' // plane:복시도, actual:실측, none:표시안함 + this.textVisible = options.textVisible ?? true if (length !== 0) { this.length = length } else { @@ -40,6 +42,9 @@ export const QLine = fabric.util.createClass(fabric.Line, { }, init: function () { + if (!this.textVisible) { + return + } this.addLengthText() this.on('moving', () => { diff --git a/src/components/fabric/QPolygon.js b/src/components/fabric/QPolygon.js index 23e0de55..f19687aa 100644 --- a/src/components/fabric/QPolygon.js +++ b/src/components/fabric/QPolygon.js @@ -23,6 +23,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { initOptions: null, direction: null, arrow: null, + toFixed: 1, initialize: function (points, options, canvas) { this.lines = [] this.texts = [] @@ -33,11 +34,12 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { this.innerLines = [] this.children = [] this.separatePolygon = [] + this.toFixed = options.toFixed ?? 1 // 소수점 전부 제거 points.forEach((point) => { - point.x = Number(point.x.toFixed(1)) - point.y = Number(point.y.toFixed(1)) + point.x = Number(point.x.toFixed(this.toFixed)) + point.y = Number(point.y.toFixed(this.toFixed)) }) options.selectable = options.selectable ?? true options.sort = options.sort ?? true @@ -77,8 +79,8 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { this.initOptions = options - this.init() this.initLines() + this.init() this.setShape() }, @@ -134,8 +136,20 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { this.on('removed', () => { // const children = getAllRelatedObjects(this.id, this.canvas) const children = this.canvas.getObjects().filter((obj) => obj.parentId === this.id) + children.forEach((child) => { this.canvas.remove(child) + + //그룹일때 + if (child.hasOwnProperty('_objects')) { + child._objects.forEach((obj) => { + if (obj.hasOwnProperty('texts')) { + obj.texts.forEach((text) => { + this.canvas?.remove(text) + }) + } + }) + } }) }) @@ -162,9 +176,10 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { }, initLines() { - // if (this.lines.length > 0) { - // return - // } + let attributes = null + if (this.lines.length > 0) { + attributes = this.lines.map((line) => line.attributes) + } this.lines = [] @@ -174,9 +189,12 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { stroke: this.stroke, strokeWidth: this.strokeWidth, fontSize: this.fontSize, - attributes: { - offset: 0, - }, + attributes: attributes + ? attributes[i] + : { + offset: 0, + }, + textVisible: false, parent: this, parentId: this.id, direction: getDirectionByPoint(point, nextPoint), @@ -272,6 +290,10 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { if ([POLYGON_TYPE.MODULE, 'arrow', POLYGON_TYPE.MODULE_SETUP_SURFACE, POLYGON_TYPE.OBJECT_SURFACE].includes(this.name)) { return } + + if (!this.fontSize) { + return + } this.canvas ?.getObjects() .filter((obj) => obj.name === 'lengthText' && obj.parentId === this.id) @@ -282,6 +304,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { let points = this.getCurrentPoints() this.texts = [] + points.forEach((start, i) => { const end = points[(i + 1) % points.length] const dx = Big(end.x).minus(Big(start.x)) @@ -313,6 +336,8 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { lockScalingX: true, lockScalingY: true, idx: i, + actualSize: this.lines[i].attributes?.actualSize, + planeSize: this.lines[i].attributes?.planeSize, name: 'lengthText', parent: this, }) diff --git a/src/components/floor-plan/CanvasFrame.jsx b/src/components/floor-plan/CanvasFrame.jsx index f5ecb10d..ddce32a6 100644 --- a/src/components/floor-plan/CanvasFrame.jsx +++ b/src/components/floor-plan/CanvasFrame.jsx @@ -13,7 +13,7 @@ import { useContextMenu } from '@/hooks/useContextMenu' import { useCanvasConfigInitialize } from '@/hooks/common/useCanvasConfigInitialize' import { currentMenuState } from '@/store/canvasAtom' import { totalDisplaySelector } from '@/store/settingAtom' -import { MENU } from '@/common/common' +import { MENU, POLYGON_TYPE } from '@/common/common' import { FloorPlanContext } from '@/app/floor-plan/FloorPlanProvider' import { QcastContext } from '@/app/QcastProvider' import { @@ -26,6 +26,10 @@ import { seriesState, } from '@/store/circuitTrestleAtom' import { useCanvasPopupStatusController } from '@/hooks/common/useCanvasPopupStatusController' +import { useCanvasSetting } from '@/hooks/option/useCanvasSetting' +import { useCanvasMenu } from '@/hooks/common/useCanvasMenu' +import { useEvent } from '@/hooks/useEvent' +import { compasDegAtom } from '@/store/orientationAtom' export default function CanvasFrame() { const canvasRef = useRef(null) @@ -42,10 +46,13 @@ export default function CanvasFrame() { const resetSelectedMakerState = useResetRecoilState(selectedMakerState) const resetSeriesState = useResetRecoilState(seriesState) const resetModelsState = useResetRecoilState(modelsState) + const resetCompasDeg = useResetRecoilState(compasDegAtom) const resetSelectedModelsState = useResetRecoilState(selectedModelsState) const resetPcsCheckState = useResetRecoilState(pcsCheckState) const { handleModuleSelectionTotal } = useCanvasPopupStatusController() - + const { basicSetting, fetchBasicSettings } = useCanvasSetting() + const { selectedMenu, setSelectedMenu } = useCanvasMenu() + const { initEvent } = useEvent() const loadCanvas = () => { if (!canvas) return @@ -56,8 +63,16 @@ export default function CanvasFrame() { canvas?.loadFromJSON(JSON.parse(plan.canvasStatus), function () { canvasLoadInit() //config된 상태로 캔버스 객체를 그린다 canvas?.renderAll() // 캔버스를 다시 그립니다. + + if (canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE).length > 0) { + setSelectedMenu('module') + } else { + setSelectedMenu('surface') + } + initEvent() }) } + Object.keys(currentCanvasPlan).length > 0 && canvas && handleModuleSelectionTotal() } gridInit() } @@ -65,7 +80,14 @@ export default function CanvasFrame() { useEffect(() => { loadCanvas() resetRecoilData() - Object.keys(currentCanvasPlan).length > 0 && handleModuleSelectionTotal() + + /* 플랜번호가 있으면 베이직세팅 팝업 데이터 로드 */ + if (currentCanvasPlan.planNo) { + /* 약간의 지연을 줘서 roofMaterials가 로드될 시간을 확보 */ + setTimeout(() => { + fetchBasicSettings(Number(currentCanvasPlan.planNo), null) + }, 100) + } }, [currentCanvasPlan, canvas]) useEffect(() => { @@ -78,11 +100,12 @@ export default function CanvasFrame() { }, []) const resetRecoilData = () => { - resetModuleStatisticsState() + // resetModuleStatisticsState() resetMakersState() resetSelectedMakerState() resetSeriesState() resetModelsState() + resetCompasDeg() resetSelectedModelsState() resetPcsCheckState() } @@ -102,12 +125,7 @@ export default function CanvasFrame() {
))} - {[ - MENU.MODULE_CIRCUIT_SETTING.BASIC_SETTING, - MENU.MODULE_CIRCUIT_SETTING.CIRCUIT_TRESTLE_SETTING, - MENU.MODULE_CIRCUIT_SETTING.PLAN_ORIENTATION, - ].includes(currentMenu) && - totalDisplay && } + {selectedMenu === 'module' && totalDisplay && } {/* 이미지 로드 팝업 */}
diff --git a/src/components/floor-plan/CanvasLayout.jsx b/src/components/floor-plan/CanvasLayout.jsx index 6a7d5ef0..43e4388a 100644 --- a/src/components/floor-plan/CanvasLayout.jsx +++ b/src/components/floor-plan/CanvasLayout.jsx @@ -14,7 +14,7 @@ import { globalLocaleStore } from '@/store/localeAtom' export default function CanvasLayout({ children }) { // const { menuNumber } = props const pathname = usePathname() - const { menuNumber } = useCanvasMenu() + const { selectedMenu } = useCanvasMenu() const { session } = useContext(SessionContext) const { floorPlanState } = useContext(FloorPlanContext) const { objectNo, pid } = floorPlanState @@ -30,7 +30,7 @@ export default function CanvasLayout({ children }) { return (
-
+
{plans.map((plan, index) => ( + -
)} - {menuNumber === 6 && ( + {selectedMenu === 'simulation' && ( <>
-
num === menuNumber) ? 'active' : ''}`}> - {[2, 3, 4].some((num) => num === menuNumber) && } +
num === selectedMenu) ? 'active' : ''}`}> + {['outline', 'surface', 'module'].some((num) => num === selectedMenu) && }
{/* 견적서(menuNumber=== 5) 상세화면인경우 문서다운로드 팝업 */} {estimatePopupOpen && ( diff --git a/src/components/floor-plan/FloorPlan.jsx b/src/components/floor-plan/FloorPlan.jsx index 6adae9a8..18f3ea0d 100644 --- a/src/components/floor-plan/FloorPlan.jsx +++ b/src/components/floor-plan/FloorPlan.jsx @@ -15,11 +15,10 @@ export default function FloorPlan({ children }) { const [correntObjectNo, setCurrentObjectNo] = useRecoilState(correntObjectNoState) const searchParams = useSearchParams() const objectNo = searchParams.get('objectNo') - const pid = searchParams.get('pid') const { closeAll } = usePopup() - const { menuNumber, setMenuNumber } = useCanvasMenu() - const { fetchSettings, fetchBasicSettings } = useCanvasSetting() + const { selectedMenu, setSelectedMenu } = useCanvasMenu() + const { fetchSettings } = useCanvasSetting() const resetCurrentMenu = useResetRecoilState(currentMenuState) useEffect(() => { return () => { @@ -27,7 +26,9 @@ export default function FloorPlan({ children }) { } }, []) - // URL 파라미터에서 objectNo 설정 + /** + * URL 파라미터에서 objectNo 설정 + */ useEffect(() => { if (!objectNo) { notFound() @@ -35,15 +36,15 @@ export default function FloorPlan({ children }) { setCurrentObjectNo(objectNo) }, [objectNo, setCurrentObjectNo]) - // 설정 데이터 fetch + /** + * 설정 데이터 fetch + */ useEffect(() => { - if (!correntObjectNo) return // correntObjectNo가 없으면 실행하지 않음 + /** correntObjectNo가 없으면 실행하지 않음 */ + if (!correntObjectNo) return - if (menuNumber === null) { - //setMenuNumber(1) - } + /** CanvasSetting 데이터 fetch */ fetchSettings() - fetchBasicSettings() return () => { closeAll() @@ -51,15 +52,17 @@ export default function FloorPlan({ children }) { }, [correntObjectNo]) const modalProps = { - menuNumber, - setMenuNumber, + selectedMenu, + setSelectedMenu, } return ( <>
-
{children}
+
+ {children} +
) diff --git a/src/components/floor-plan/MenuDepth01.jsx b/src/components/floor-plan/MenuDepth01.jsx index c1f40140..ae35a3a3 100644 --- a/src/components/floor-plan/MenuDepth01.jsx +++ b/src/components/floor-plan/MenuDepth01.jsx @@ -6,32 +6,33 @@ import { useMessage } from '@/hooks/useMessage' import useMenu from '@/hooks/common/useMenu' import { canvasState, currentMenuState } from '@/store/canvasAtom' import { useRecoilState, useRecoilValue } from 'recoil' -import { menuTypeState, subMenusState } from '@/store/menuAtom' +import { subMenusState } from '@/store/menuAtom' +import { useCanvasMenu } from '@/hooks/common/useCanvasMenu' export default function MenuDepth01() { - const type = useRecoilValue(menuTypeState) const canvas = useRecoilValue(canvasState) const { getMessage } = useMessage() const { handleMenu } = useMenu() + const { selectedMenu, setSelectedMenu } = useCanvasMenu() const [currentMenu, setCurrentMenu] = useRecoilState(currentMenuState) const subMenus = useRecoilValue(subMenusState) const onClickMenu = ({ id, menu }) => { if (menu === currentMenu) { - handleMenu(type) + handleMenu(selectedMenu) } else { setCurrentMenu(menu) } } useEffect(() => { - handleMenu(type) + handleMenu(selectedMenu) canvas?.discardActiveObject() }, [currentMenu]) return (
    - {subMenus[type]?.map((menu) => { + {subMenus[selectedMenu]?.map((menu) => { return (
  • diff --git a/src/components/floor-plan/modal/ImgLoad.jsx b/src/components/floor-plan/modal/ImgLoad.jsx index fdff181f..dda395a9 100644 --- a/src/components/floor-plan/modal/ImgLoad.jsx +++ b/src/components/floor-plan/modal/ImgLoad.jsx @@ -12,6 +12,10 @@ import { useCanvas } from '@/hooks/useCanvas' import { useImgLoader } from '@/hooks/floorPlan/useImgLoader' // import { initImageLoaderPopup } from '@/lib/planAction' +/** + * 이미지 로드 모달 + * @returns + */ export default function ImgLoad() { const { currentCanvasPlan, setCurrentCanvasPlan } = usePlan() const { getMessage } = useMessage() @@ -72,97 +76,88 @@ export default function ImgLoad() { }, [currentCanvasPlan]) return ( - -
    -
    -

    {getMessage('common.input.file')}

    - + + setFloorPlanState({ ...floorPlanState, refFileModalOpen: false })} + /> + + +
    + {getMessage('modal.image.load.size.rotate')} +
    -
    -
    - {getMessage('modal.image.load.size.rotate')} - -
    -
    -
    -
    - handleRefFileMethod(e)} checked={refFileMethod === '1'} /> - -
    -
    -
    - - handleRefFile(e.target.files[0]) : () => {}} - /> -
    -
    - - {refImage && } -
    -
    +
    +
    +
    + handleRefFileMethod(e)} checked={refFileMethod === '1'} /> +
    -
    -
    - handleRefFileMethod(e)} checked={refFileMethod === '2'} /> - +
    +
    + + handleRefFile(e.target.files[0]) : () => {}} + />
    -
    +
    setMapPositionAddress(e.target.value)} + className="input-origin al-l" + value={refImage ? (refImage?.name ?? '') : (currentCanvasPlan?.bgImageName ?? '')} + readOnly /> -
    - -
    - {mapPositionAddress && } - {/* */} + {refImage && }
    -
    - - {/* */} +
    +
    + handleRefFileMethod(e)} checked={refFileMethod === '2'} /> + +
    +
    + setMapPositionAddress(e.target.value)} + /> +
    + +
    + {mapPositionAddress && } + {/* */} +
    -
    -
    +
    + + {/* */} +
    + ) } diff --git a/src/components/floor-plan/modal/Slope.jsx b/src/components/floor-plan/modal/Slope.jsx index 58ccec4d..df4a25d7 100644 --- a/src/components/floor-plan/modal/Slope.jsx +++ b/src/components/floor-plan/modal/Slope.jsx @@ -13,40 +13,32 @@ export default function Slope({ id, pos = { x: 50, y: 230 } }) { const inputRef = useRef() return ( - -
    -
    -

    {getMessage('plan.menu.placement.surface.slope.setting')}

    -
    -
    -
    -
    - - {getMessage('slope')} - -
    - -
    - {pitchText} -
    -
    -
    - -
    -
    -
    -
    +
    ) } diff --git a/src/components/floor-plan/modal/auxiliary/AuxiliaryDrawing.jsx b/src/components/floor-plan/modal/auxiliary/AuxiliaryDrawing.jsx index b85d76c6..1417b501 100644 --- a/src/components/floor-plan/modal/auxiliary/AuxiliaryDrawing.jsx +++ b/src/components/floor-plan/modal/auxiliary/AuxiliaryDrawing.jsx @@ -124,44 +124,36 @@ export default function AuxiliaryDrawing({ id, pos = { x: 50, y: 230 } }) { setType(button.type) } return ( - -
    -
    -

    {getMessage('modal.auxiliary.drawing')}

    - + ))} +
    +
    +
    {getMessage('setting')}
    + {buttonAct === 1 && } + {buttonAct === 2 && } + {buttonAct === 3 && } + {buttonAct === 4 && } + {buttonAct === 5 && } +
    +
    + + +
    -
    -
    - {types.map((type, idx) => ( - - ))} -
    -
    -
    {getMessage('setting')}
    - {buttonAct === 1 && } - {buttonAct === 2 && } - {buttonAct === 3 && } - {buttonAct === 4 && } - {buttonAct === 5 && } -
    -
    - - - -
    -
    -
    -
    +
    ) } diff --git a/src/components/floor-plan/modal/auxiliary/AuxiliaryEdit.jsx b/src/components/floor-plan/modal/auxiliary/AuxiliaryEdit.jsx index 1da94050..744b3387 100644 --- a/src/components/floor-plan/modal/auxiliary/AuxiliaryEdit.jsx +++ b/src/components/floor-plan/modal/auxiliary/AuxiliaryEdit.jsx @@ -26,12 +26,12 @@ export default function AuxiliaryEdit(props) { return } - if ((verticalSize && +verticalSize === 0) || !arrow1) { + if (verticalSize && +verticalSize !== 0 && !arrow1) { swalFire({ title: getMessage('length.direction.is.required'), type: 'alert' }) return } - if ((horizonSize && +horizonSize === 0) || !arrow2) { + if (horizonSize && +horizonSize !== 0 && !arrow2) { swalFire({ title: getMessage('length.direction.is.required'), type: 'alert' }) return } @@ -55,75 +55,67 @@ export default function AuxiliaryEdit(props) { closePopup(id) } return ( - -
    -
    -

    {getMessage(type === 'copy' ? 'modal.auxiliary.copy' : 'modal.auxiliary.move')}

    - -
    -
    -
    {getMessage(type === 'copy' ? 'modal.auxiliary.copy.info' : 'modal.auxiliary.move.info')}
    -
    -
    -
    -

    {getMessage('length')}

    -
    -
    - setVerticalSize(e.target.value)} /> -
    - mm -
    - - -
    + + closePopup(id)} /> + +
    {getMessage(type === 'copy' ? 'modal.auxiliary.copy.info' : 'modal.auxiliary.move.info')}
    +
    +
    +
    +

    {getMessage('length')}

    +
    +
    + setVerticalSize(e.target.value)} />
    -
    -
    - setHorizonSize(e.target.value)} /> -
    - mm -
    - - -
    + mm +
    + + +
    +
    +
    +
    + setHorizonSize(e.target.value)} /> +
    + mm +
    + +
    -
    - -
    -
    -
    +
    + +
    +
    ) } diff --git a/src/components/floor-plan/modal/auxiliary/AuxiliarySize.jsx b/src/components/floor-plan/modal/auxiliary/AuxiliarySize.jsx index f8bf4ca7..3bb94a4f 100644 --- a/src/components/floor-plan/modal/auxiliary/AuxiliarySize.jsx +++ b/src/components/floor-plan/modal/auxiliary/AuxiliarySize.jsx @@ -111,61 +111,53 @@ export default function AuxiliarySize(props) { closePopup(id) } return ( - -
    -
    -

    {getMessage('modal.auxiliary.size.edit')}

    -
    -
    -
    -
    - setCheckedRadio(1)} /> - -
    -
    -
    - -
    - mm -
    -
    - {getMessage('length')} -
    - -
    - mm -
    -
    -
    -
    - setCheckedRadio(2)} /> - -
    -
    -
    - -
    - mm -
    -
    - {getMessage('length')} -
    - -
    - mm -
    -
    -
    - -
    -
    -
    -
    +
    ) } diff --git a/src/components/floor-plan/modal/basic/BasicSetting.jsx b/src/components/floor-plan/modal/basic/BasicSetting.jsx index 3baa57e2..f312d5ea 100644 --- a/src/components/floor-plan/modal/basic/BasicSetting.jsx +++ b/src/components/floor-plan/modal/basic/BasicSetting.jsx @@ -6,12 +6,12 @@ import PitchModule from '@/components/floor-plan/modal/basic/step/pitch/PitchMod import PitchPlacement from '@/components/floor-plan/modal/basic/step/pitch/PitchPlacement' import Placement from '@/components/floor-plan/modal/basic/step/Placement' import { useRecoilValue, useRecoilState } from 'recoil' -import { canvasSettingState, canvasState, isManualModuleSetupState } from '@/store/canvasAtom' +import { canvasSettingState, canvasState, checkedModuleState, isManualModuleSetupState } from '@/store/canvasAtom' import { usePopup } from '@/hooks/usePopup' import { Orientation } from '@/components/floor-plan/modal/basic/step/Orientation' import { useModuleBasicSetting } from '@/hooks/module/useModuleBasicSetting' import { useEvent } from '@/hooks/useEvent' -import { moduleSelectionDataState } from '@/store/selectedModuleOptions' +import { moduleSelectionDataState, selectedModuleState } from '@/store/selectedModuleOptions' import { addedRoofsState, corridorDimensionSelector, basicSettingState } from '@/store/settingAtom' import { isObjectNotEmpty } from '@/util/common-utils' import Swal from 'sweetalert2' @@ -36,10 +36,12 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) { const canvas = useRecoilValue(canvasState) const [basicSetting, setBasicSettings] = useRecoilState(basicSettingState) const [isClosePopup, setIsClosePopup] = useState({ close: false, id: 0 }) + const [checkedModules, setCheckedModules] = useRecoilState(checkedModuleState) // const { initEvent } = useContext(EventContext) const { manualModuleSetup, autoModuleSetup, manualFlatroofModuleSetup, autoFlatroofModuleSetup } = useModuleBasicSetting(tabNum) const { updateObjectDate } = useMasterController() + const handleBtnNextStep = () => { if (tabNum === 1) { orientationRef.current.handleNextStep() @@ -70,7 +72,7 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) { userId: loginUserState.userId, //작성자아아디 }) } else { - if (!isObjectNotEmpty(moduleSelectionData.flatModule)) { + if (!isObjectNotEmpty(moduleSelectionData.module)) { Swal.fire({ title: getMessage('module.not.found'), icon: 'warning', @@ -134,75 +136,71 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) { } }, [isManualModuleSetup, isClosePopup]) - return ( - -
    -
    -

    {getMessage('plan.menu.module.circuit.setting.default')}

    - -
    -
    -
    -
    {getMessage('modal.module.basic.setting.orientation.setting')}
    - -
    {getMessage('modal.module.basic.setting.module.setting')}
    - -
    {getMessage('modal.module.basic.setting.module.placement')}
    -
    - {tabNum === 1 && } - {/*배치면 초기설정 - 입력방법: 복시도 입력 || 실측값 입력*/} - {basicSetting.roofSizeSet && basicSetting.roofSizeSet != '3' && tabNum === 2 && } - {basicSetting.roofSizeSet && basicSetting.roofSizeSet != '3' && tabNum === 3 && } + useEffect(() => { + setIsManualModuleSetup(false) + }, [checkedModules]) - {/*배치면 초기설정 - 입력방법: 육지붕*/} - {basicSetting.roofSizeSet && basicSetting.roofSizeSet == '3' && tabNum === 2 && } - {basicSetting.roofSizeSet && basicSetting.roofSizeSet == '3' && tabNum === 3 && ( - + return ( + + handleClosePopup(id)} /> + +
    +
    {getMessage('modal.module.basic.setting.orientation.setting')}
    + +
    {getMessage('modal.module.basic.setting.module.setting')}
    + +
    {getMessage('modal.module.basic.setting.module.placement')}
    +
    + {tabNum === 1 && } + {/*배치면 초기설정 - 입력방법: 복시도 입력 || 실측값 입력*/} + {basicSetting.roofSizeSet && basicSetting.roofSizeSet != '3' && tabNum === 2 && } + {basicSetting.roofSizeSet && basicSetting.roofSizeSet != '3' && tabNum === 3 && } + + {/*배치면 초기설정 - 입력방법: 육지붕*/} + {basicSetting.roofSizeSet && basicSetting.roofSizeSet == '3' && tabNum === 2 && } + {basicSetting.roofSizeSet && basicSetting.roofSizeSet == '3' && tabNum === 3 && ( + + )} + +
    + {tabNum !== 1 && ( + + )} + {/*{tabNum !== 3 && }*/} + {tabNum !== 3 && ( + )} -
    - {tabNum !== 1 && ( - - )} - {/*{tabNum !== 3 && }*/} - {tabNum !== 3 && ( - - )} - - {tabNum === 3 && ( - <> - {basicSetting.roofSizeSet && basicSetting.roofSizeSet != '3' && ( - <> - - - - )} - {basicSetting.roofSizeSet && basicSetting.roofSizeSet == '3' && ( - <> - - - - )} - - )} -
    + {tabNum === 3 && ( + <> + {basicSetting.roofSizeSet && basicSetting.roofSizeSet != '3' && ( + <> + + + + )} + {basicSetting.roofSizeSet && basicSetting.roofSizeSet == '3' && ( + <> + + + + )} + + )}
    -
    -
    + ) } diff --git a/src/components/floor-plan/modal/basic/step/ModuleTabContents.jsx b/src/components/floor-plan/modal/basic/step/ModuleTabContents.jsx index 75c8dcd9..7cdef358 100644 --- a/src/components/floor-plan/modal/basic/step/ModuleTabContents.jsx +++ b/src/components/floor-plan/modal/basic/step/ModuleTabContents.jsx @@ -3,10 +3,13 @@ import { useMessage } from '@/hooks/useMessage' import { isObjectNotEmpty } from '@/util/common-utils' import QSelectBox from '@/components/common/select/QSelectBox' import { useModuleTabContents } from '@/hooks/module/useModuleTabContents' +import { useRecoilValue } from 'recoil' +import { ANGLE_TYPE, currentAngleTypeSelector } from '@/store/canvasAtom' export default function ModuleTabContents({ tabIndex, addRoof, setAddedRoofs, roofTab, tempModuleSelectionData, setTempModuleSelectionData }) { const { getMessage } = useMessage() const [roofMaterial, setRoofMaterial] = useState(addRoof) //지붕재` + const currentAngleType = useRecoilValue(currentAngleTypeSelector) const { raftCodes, @@ -45,7 +48,7 @@ export default function ModuleTabContents({ tabIndex, addRoof, setAddedRoofs, ro
    {getMessage('modal.module.basic.setting.module.roof.material')}:{roofMaterial.nameJp}( - {addRoof.roofAngleSet === 'slope' ? roofMaterial.pitch : roofMaterial.angle} + {currentAngleType === ANGLE_TYPE.SLOPE ? roofMaterial.pitch : roofMaterial.angle} {globalPitchText})
    diff --git a/src/components/floor-plan/modal/basic/step/Placement.jsx b/src/components/floor-plan/modal/basic/step/Placement.jsx index e8d8048f..d4b979c7 100644 --- a/src/components/floor-plan/modal/basic/step/Placement.jsx +++ b/src/components/floor-plan/modal/basic/step/Placement.jsx @@ -1,7 +1,7 @@ import { forwardRef, useEffect, useState } from 'react' import { useMessage } from '@/hooks/useMessage' import { useModuleBasicSetting } from '@/hooks/module/useModuleBasicSetting' -import { checkedModuleState, currentCanvasPlanState } from '@/store/canvasAtom' +import { checkedModuleState, currentCanvasPlanState, isManualModuleSetupState } from '@/store/canvasAtom' import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil' import { moduleSelectionDataState, selectedModuleState } from '@/store/selectedModuleOptions' import { isObjectNotEmpty } from '@/util/common-utils' @@ -23,6 +23,8 @@ const Placement = forwardRef((props, refs) => { const [isMultiModule, setIsMultiModule] = useState(false) + const [isManualModuleSetup, setIsManualModuleSetup] = useRecoilState(isManualModuleSetupState) + //모듈 배치면 생성 useEffect(() => { if (moduleSelectionData) { @@ -33,6 +35,10 @@ const Placement = forwardRef((props, refs) => { } makeModuleInitArea(moduleSelectionData) } + + return () => { + setIsManualModuleSetup(false) + } }, []) //최초 지입시 체크 @@ -53,7 +59,7 @@ const Placement = forwardRef((props, refs) => { } //모듈 배치면 생성 - if (moduleSelectionData.module.itemList.length > 1) { + if (isObjectNotEmpty(moduleSelectionData.module) && moduleSelectionData.module.itemList.length > 1) { setIsMultiModule(true) } } diff --git a/src/components/floor-plan/modal/basic/step/pitch/PitchModule.jsx b/src/components/floor-plan/modal/basic/step/pitch/PitchModule.jsx index 39d0ee19..e248c272 100644 --- a/src/components/floor-plan/modal/basic/step/pitch/PitchModule.jsx +++ b/src/components/floor-plan/modal/basic/step/pitch/PitchModule.jsx @@ -47,17 +47,17 @@ export default function PitchModule({}) { setSelectedModules(option) //선택값 저장 setModuleSelectionData({ ...moduleSelectionData, - flatModule: option, + module: option, }) moduleSelectedDataTrigger({ ...moduleSelectionData, - flatModule: option, + module: option, }) } useEffect(() => { - if (isObjectNotEmpty(moduleSelectionData.flatModule) && moduleList.length > 0) { - handleChangeModule(moduleSelectionData.flatModule) + if (isObjectNotEmpty(moduleSelectionData.module) && moduleList.length > 0) { + handleChangeModule(moduleSelectionData.module) } }, [moduleList]) diff --git a/src/components/floor-plan/modal/basic/step/pitch/PitchPlacement.jsx b/src/components/floor-plan/modal/basic/step/pitch/PitchPlacement.jsx index 64d91881..b4137ac6 100644 --- a/src/components/floor-plan/modal/basic/step/pitch/PitchPlacement.jsx +++ b/src/components/floor-plan/modal/basic/step/pitch/PitchPlacement.jsx @@ -69,7 +69,7 @@ const PitchPlacement = forwardRef((props, refs) => { excretaLine.forEach((line) => { line.set({ stroke: '#642EFB', - strokeWidth: 5, + strokeWidth: 3, surfaceId: surface.surfaceId, name: 'flatExcretaLine', }) @@ -89,10 +89,10 @@ const PitchPlacement = forwardRef((props, refs) => { } useEffect(() => { - if (!moduleSelectionData.flatModule) return // null 오류 차단 로직 추가 - if (moduleSelectionData && moduleSelectionData.flatModule.itemList.length > 0) { + if (!moduleSelectionData.module) return // null 오류 차단 로직 추가 + if (moduleSelectionData && moduleSelectionData.module.itemList.length > 0) { let initCheckedModule = {} - moduleSelectionData.flatModule.itemList.forEach((obj, index) => { + moduleSelectionData.module.itemList.forEach((obj, index) => { if (index === 0) { initCheckedModule = { [obj.itemId]: true } } else { diff --git a/src/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting.jsx b/src/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting.jsx index d53c1f4f..618a65d2 100644 --- a/src/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting.jsx +++ b/src/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting.jsx @@ -1,5 +1,5 @@ import WithDraggable from '@/components/common/draggable/WithDraggable' -import { useState, useEffect, useContext } from 'react' +import { useState, useEffect, useContext, useRef } from 'react' import PowerConditionalSelect from '@/components/floor-plan/modal/circuitTrestle/step/PowerConditionalSelect' import StepUp from '@/components/floor-plan/modal/circuitTrestle/step/StepUp' import { useMessage } from '@/hooks/useMessage' @@ -33,7 +33,7 @@ const ALLOCATION_TYPE = { export default function CircuitTrestleSetting({ id }) { const { getMessage } = useMessage() const { closePopup } = usePopup() - const { apply, setViewCircuitNumberTexts } = useTrestle() + const { apply, setViewCircuitNumberTexts, getEstimateData, clear: clearTrestle, setAllModuleSurfaceIsComplete } = useTrestle() const { swalFire } = useSwal() const { saveEstimate } = useEstimate() const canvas = useRecoilValue(canvasState) @@ -43,7 +43,7 @@ export default function CircuitTrestleSetting({ id }) { const [circuitAllocationType, setCircuitAllocationType] = useState(1) const { managementState, setManagementState, managementStateLoaded } = useContext(GlobalDataContext) const selectedModules = useRecoilValue(selectedModuleState) - const { getPcsAutoRecommendList, getPcsVoltageChk, getPcsVoltageStepUpList } = useMasterController() + const { getPcsAutoRecommendList, getPcsVoltageChk, getPcsVoltageStepUpList, getPcsManualConfChk } = useMasterController() // 회로할당(승합설정)에서 선택된 값들을 저장할 상태 추가 const [selectedStepUpValues, setSelectedStepUpValues] = useState({}) @@ -51,12 +51,12 @@ export default function CircuitTrestleSetting({ id }) { // const { trigger: setCircuitData } = useCanvasPopupStatusController(4) // const [stepUpListData, setStepUpListData] = useRecoilState(stepUpListDataState) const [stepUpListData, setStepUpListData] = useState([]) - const [seletedOption, setSeletedOption] = useState(null) + const [seletedMainOption, setSeletedMainOption] = useState(null) + const [seletedSubOption, setSeletedSubOption] = useState(null) const { setModuleStatisticsData } = useCircuitTrestle() - const { handleCanvasToPng } = useImgLoader() - const { saveCanvas } = usePlan() + const passivityCircuitAllocationRef = useRef() const { setIsGlobalLoading } = useContext(QcastContext) const { @@ -79,6 +79,7 @@ export default function CircuitTrestleSetting({ id }) { getRoofSurfaceList, getModuleList, removeNotAllocationModules, + resetCircuits, } = useCircuitTrestle() // const { trigger: moduleSelectedDataTrigger } = useCanvasPopupStatusController(2) useEffect(() => { @@ -93,6 +94,13 @@ export default function CircuitTrestleSetting({ id }) { // selectedModels, // pcsCheck, // }) + + return () => { + const moduleSetupSurfaces = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE) + if (moduleSetupSurfaces.some((surface) => !surface.isComplete)) { + resetCircuits() + } + } }, []) // 수동할당 시 모듈 삭제 @@ -331,6 +339,8 @@ export default function CircuitTrestleSetting({ id }) { // 회로할당(승압설정) 저장 버튼 클릭 시 const onApply = async () => { + setAllModuleSurfaceIsComplete(false) + setIsGlobalLoading(true) canvas .getObjects() @@ -343,19 +353,29 @@ export default function CircuitTrestleSetting({ id }) { handleCanvasToPng(1) - //회로할당 저장 클릭 시 - const result = await apply() - //회로할당 저장 시 result=null인 경우에도 회로번호 텍스트 표시 유지 처리 setViewCircuitNumberTexts(true) + // 회로할당 저장 클릭 시 + // 가대 및 지지금구 설치 + // apply() + // apply() 결과를 체크하여 null이면 함수 종료 + const applyResult = apply() + if (!applyResult) { + setIsGlobalLoading(false) + return + } + + const result = await getEstimateData() + if (result) { handleCanvasToPng(2) - // 캔버스 저장 - await saveCanvas(false) // 견적서 저장 await saveEstimate(result) + } else { + setIsGlobalLoading(false) } + // removeNotAllocationModules() } @@ -374,6 +394,12 @@ export default function CircuitTrestleSetting({ id }) { obj.pcsItemId = null obj.circuitNumber = null }) + setSelectedModels( + JSON.parse(JSON.stringify(selectedModels)).map((model) => { + model.isUsed = false + return model + }), + ) if (allocationType === ALLOCATION_TYPE.PASSIVITY) { setAllocationType(ALLOCATION_TYPE.AUTO) @@ -381,6 +407,7 @@ export default function CircuitTrestleSetting({ id }) { } else { setTabNum(1) } + clearTrestle() canvas.renderAll() setModuleStatisticsData() @@ -427,6 +454,7 @@ export default function CircuitTrestleSetting({ id }) { allocationType, circuitAllocationType, setCircuitAllocationType, + selectedMaker, selectedModels, setSelectedModels, getSelectedPcsItemList, @@ -437,23 +465,27 @@ export default function CircuitTrestleSetting({ id }) { onValuesSelected: handleStepUpValuesSelected, // 선택된 값들을 처리하는 함수 stepUpListData, setStepUpListData, - seletedOption, - setSeletedOption, + seletedMainOption, + setSeletedMainOption, + seletedSubOption, + setSeletedSubOption, getModuleList, setModuleStatisticsData, } // 승압설정 목록 조회 const getStepUpListData = () => { - return stepUpListData[0].pcsItemList.map((item) => { + const pcs = [] + console.log(stepUpListData) + stepUpListData[0].pcsItemList.map((item, index) => { return item.serQtyList .filter((serQty) => serQty.selected) - .map((serQty) => { - return { + .forEach((serQty) => { + pcs.push({ pcsMkrCd: item.pcsMkrCd, pcsSerCd: item.pcsSerCd, pcsItemId: item.itemId, - pscOptCd: seletedOption.code, + pscOptCd: getPcsOptCd(index), paralQty: serQty.paralQty, connections: item.connList?.length ? [ @@ -462,97 +494,219 @@ export default function CircuitTrestleSetting({ id }) { }, ] : [], - } - })[0] + }) + // return { + // pcsMkrCd: item.pcsMkrCd, + // pcsSerCd: item.pcsSerCd, + // pcsItemId: item.itemId, + // pscOptCd: getPcsOptCd(index), + // paralQty: serQty.paralQty, + // connections: item.connList?.length + // ? [ + // { + // connItemId: item.connList[0].itemId, + // }, + // ] + // : [], + // } + }) }) + return pcs + } + + const getPcsOptCd = (index) => { + console.log(selectedModels) + console.log(seletedMainOption) + console.log(seletedSubOption) + if (selectedModels.some((model) => model.pcsSerParallelYn === 'Y')) { + if (selectedModels.length > 1) { + if (index === 0) { + return seletedMainOption.code + } else { + return seletedSubOption.code + } + } else { + return seletedMainOption.code + } + } else { + return seletedMainOption.code + } } const handleStepUp = () => { - const notAllocationModules = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE && !obj.circuit) - if (notAllocationModules.length > 0) { - swalFire({ - title: getMessage('not.allocation.exist.module'), - type: 'alert', - }) - return - } - setTabNum(2) + handlePassivityAllocationCkeck() + // const notAllocationModules = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE && !obj.circuit) + // if (notAllocationModules.length > 0) { + // swalFire({ + // title: getMessage('not.allocation.exist.module'), + // type: 'alert', + // }) + // return + // } else { + // passivityCircuitAllocationRef.current.onApply() + // setTabNum(2) + // } } // 닫기 버튼 클릭 시 처리하는 함수 추가 const handleClose = () => { // // 회로 번호 텍스트 제거 - // const circuitTexts = canvas.getObjects().filter((obj) => obj.name === 'circuitNumber') - // canvas.remove(...circuitTexts) - // // 모듈의 회로 정보 초기화 - // canvas - // .getObjects() - // .filter((obj) => obj.name === POLYGON_TYPE.MODULE) - // .forEach((obj) => { - // obj.circuit = null - // obj.pcsItemId = null - // obj.circuitNumber = null - // }) + if ( + canvas + .getObjects() + .filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE) + .some((surface) => !surface.isComplete) + ) { + canvas.remove(...canvas.getObjects().filter((obj) => obj.name === 'circuitNumber')) + canvas + .getObjects() + .filter((obj) => obj.name === POLYGON_TYPE.MODULE) + .forEach((obj) => { + obj.circuit = null + obj.pcsItemId = null + obj.circuitNumber = null + }) + + canvas.renderAll() + } - // canvas.renderAll() closePopup(id) } + const handlePassivityAllocationCkeck = () => { + let pcsCount = {} + let result = {} + const notAllocationModules = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE && !obj.circuit) + if (notAllocationModules.length > 0) { + swalFire({ + text: getMessage('not.allocation.exist.module'), + type: 'alert', + icon: 'warning', + }) + return + } + canvas + .getObjects() + .filter((obj) => obj.name === POLYGON_TYPE.MODULE) + .forEach((module) => { + const circuitNumber = module.circuitNumber.replace(/[()]/g, '') + pcsCount[circuitNumber] = (pcsCount[circuitNumber] || 0) + 1 + }) + for (const key in pcsCount) { + const firstPart = key.split('-')[0] // '-' 기준으로 첫 번째 부분을 추출 + const value = pcsCount[key] + + // 그룹이 없으면 초기화 + if (!result[firstPart]) { + result[firstPart] = { maxValue: value, count: 1 } + } else { + // 이미 그룹이 있으면 큰 값으로 갱신, count는 증가 + result[firstPart].maxValue = Math.max(result[firstPart].maxValue, value) + result[firstPart].count += 1 + } + } + const params = { + ...getOptYn(), + useModuleItemList: getUseModuleItemList(), + roofSurfaceList: getRoofSurfaceList(), + pcsItemList: selectedModels.map((model, index) => { + return { + pcsMkrCd: model.pcsMkrCd, + pcsSerCd: model.pcsSerCd, + itemId: model.itemId, + itemNm: model.itemNm, + goodsNo: model.goodsNo, + serQtyList: [ + { + 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 + .getObjects() + .filter((obj) => POLYGON_TYPE.MODULE_SETUP_SURFACE === obj.name && obj?.modules.length > 0) + .map((surface) => { + return { + roofSurfaceId: surface.id, + roofSurface: surface.direction, + roofSurfaceIncl: +canvas.getObjects().filter((obj) => obj.id === surface.parentId)[0].pitch, + moduleList: surface.modules.map((module) => { + return { + itemId: module.moduleInfo.itemId, + circuit: module.circuitNumber, + pcsItemId: module.pcsItemId, + } + }), + } + }), + }, + ], + } + }), + } + + getPcsManualConfChk(params).then((res) => { + if (res?.resultCode === 'E') { + swalFire({ + text: res.resultMsg, + type: 'alert', + icon: 'warning', + }) + return + } else { + setTabNum(2) + } + }) + } + return ( - -
    -
    -

    {getMessage('modal.circuit.trestle.setting')}

    - {/* -
    -
    -
    -
    {getMessage('modal.circuit.trestle.setting.power.conditional.select')}
    - -
    - {getMessage('modal.circuit.trestle.setting.circuit.allocation')}({getMessage('modal.circuit.trestle.setting.step.up.allocation')}) -
    + + handleClose()} /> + +
    +
    {getMessage('modal.circuit.trestle.setting.power.conditional.select')}
    + +
    + {getMessage('modal.circuit.trestle.setting.circuit.allocation')}({getMessage('modal.circuit.trestle.setting.step.up.allocation')})
    - {tabNum === 1 && allocationType === ALLOCATION_TYPE.AUTO && } - {tabNum === 1 && allocationType === ALLOCATION_TYPE.PASSIVITY && } - {tabNum === 2 && } - {tabNum === 1 && allocationType === ALLOCATION_TYPE.AUTO && ( -
    - - -
    - )} - {tabNum === 1 && allocationType === ALLOCATION_TYPE.PASSIVITY && ( -
    - - -
    - )} - {tabNum === 2 && ( -
    - - {/* -
    - )}
    -
    -
    + {tabNum === 1 && allocationType === ALLOCATION_TYPE.AUTO && } + {tabNum === 1 && allocationType === ALLOCATION_TYPE.PASSIVITY && ( + + )} + {tabNum === 2 && } + {tabNum === 1 && allocationType === ALLOCATION_TYPE.AUTO && ( +
    + + +
    + )} + {tabNum === 1 && allocationType === ALLOCATION_TYPE.PASSIVITY && ( +
    + + +
    + )} + {tabNum === 2 && ( +
    + + {/* +
    + )} + ) } diff --git a/src/components/floor-plan/modal/circuitTrestle/step/PowerConditionalSelect.jsx b/src/components/floor-plan/modal/circuitTrestle/step/PowerConditionalSelect.jsx index 5957103c..f8d1d530 100644 --- a/src/components/floor-plan/modal/circuitTrestle/step/PowerConditionalSelect.jsx +++ b/src/components/floor-plan/modal/circuitTrestle/step/PowerConditionalSelect.jsx @@ -13,6 +13,12 @@ import { useRecoilState } from 'recoil' import { useRecoilValue } from 'recoil' import { v4 as uuidv4 } from 'uuid' +export const PCS_MKR_MULTI_TYPE = { + MULTI: 'MULTI', + SINGLE_P: 'SINGLE-P', + SINGLE_N: 'SINGLE-N', +} + export default function PowerConditionalSelect(props) { let { tabNum, @@ -75,18 +81,26 @@ export default function PowerConditionalSelect(props) { const onCheckSeries = (data) => { let copySeries = [] - if (data.pcsMkrMultiType === 'MULTI') { + if (data.pcsMkrMultiType === PCS_MKR_MULTI_TYPE.MULTI) { copySeries = series.map((s) => { return { ...s, selected: s.pcsSerCd === data.pcsSerCd ? !s.selected : s.selected, } }) - } else if (data.pcsMkrMultiType === 'SINGLE-P') { + } else if (data.pcsMkrMultiType === PCS_MKR_MULTI_TYPE.SINGLE_P) { + if (series.filter((s) => s.selected).length === 0 && data.pcsSerParallelYn === 'Y') { + swalFire({ + title: getMessage('modal.module.pcs.error1'), + icon: 'warning', + }) + + return + } copySeries = series.map((s) => { return { ...s, - selected: s.pcsSerCd === data.pcsSerCd ? !s.selected : s.pcsMkrMultiType === 'MULTI' ? s.selected : false, + selected: s.pcsSerCd === data.pcsSerCd ? !s.selected : data.pcsSerParallelYn === 'Y' ? s.selected : false, } }) } else { @@ -107,7 +121,6 @@ export default function PowerConditionalSelect(props) { setSelectedModels([]) return } - console.log('moduleSelectionData', moduleSelectionData) const pcsMkrCd = selectedSeries[0]?.pcsMkrCd const pcsSerList = selectedSeries.map((series) => { return { pcsSerCd: series.pcsSerCd } @@ -147,15 +160,34 @@ export default function PowerConditionalSelect(props) { return } - if (selectedMaker.pcsMkrMultiType === 'MULTI') { - setSelectedModels([...selectedModels, { ...selectedRow, id: uuidv4(), isUsed: false }]) + + if (selectedModels.find((m) => m.pcsSerParallelYn === 'Y') && selectedRow.pcsSerParallelYn === 'Y') { + return + } + + if (selectedRow.pcsSerParallelYn === 'Y' && selectedModels.length === 0 && selectedMaker.pcsMkrMultiType === PCS_MKR_MULTI_TYPE.SINGLE_P) { + swalFire({ + title: getMessage('modal.module.pcs.error1'), + icon: 'warning', + }) + + return + } + + if (selectedMaker.pcsMkrMultiType === PCS_MKR_MULTI_TYPE.MULTI) { + setSelectedModels([...selectedModels, { ...selectedRow, id: uuidv4() }]) } else if (!selectedModels.find((m) => m.itemId === selectedRow.itemId)) { - setSelectedModels([...selectedModels, { ...selectedRow, id: uuidv4(), isUsed: false }]) + setSelectedModels([...selectedModels, { ...selectedRow, id: uuidv4() }]) } setSelectedRow(null) } const onRemoveSelectedModel = (model) => { + const tempModels = selectedModels.filter((m) => m.id !== model.id) + if (tempModels.length === 1 && tempModels[0].pcsSerParallelYn === 'Y') { + setSelectedModels([]) + return + } setSelectedModels(selectedModels.filter((m) => m.id !== model.id)) } @@ -264,14 +296,6 @@ export default function PowerConditionalSelect(props) {
    - {/*
    - - -
    */} ) } diff --git a/src/components/floor-plan/modal/circuitTrestle/step/StepUp.jsx b/src/components/floor-plan/modal/circuitTrestle/step/StepUp.jsx index d8fa01e5..d776476b 100644 --- a/src/components/floor-plan/modal/circuitTrestle/step/StepUp.jsx +++ b/src/components/floor-plan/modal/circuitTrestle/step/StepUp.jsx @@ -15,6 +15,7 @@ import { POLYGON_TYPE } from '@/common/common' import { useSwal } from '@/hooks/useSwal' import { circuitNumDisplaySelector } from '@/store/settingAtom' import { fontSelector } from '@/store/fontAtom' +import { PCS_MKR_MULTI_TYPE } from './PowerConditionalSelect' export default function StepUp(props) { const { @@ -22,8 +23,11 @@ export default function StepUp(props) { allocationType, stepUpListData, setStepUpListData, - seletedOption, - setSeletedOption, + seletedMainOption, + setSeletedMainOption, + seletedSubOption, + setSeletedSubOption, + selectedMaker, selectedModels, setSelectedModels, getSelectedPcsItemList, @@ -42,23 +46,18 @@ export default function StepUp(props) { const canvas = useRecoilValue(canvasState) const selectedModules = useRecoilValue(selectedModuleState) const [optCodes, setOptCodes] = useState([]) + const [mainOptions, setMainOptions] = useState([]) + const [subOptions, setSubOptions] = useState([]) const [selectedRows, setSelectedRows] = useState({}) const [isManualSelection, setIsManualSelection] = useState({}) - // 선택된 값들을 저장할 상태 추가 - const [selectedValues, setSelectedValues] = useState({}) const isDisplayCircuitNumber = useRecoilValue(circuitNumDisplaySelector) const circuitNumberText = useRecoilValue(fontSelector('circuitNumberText')) - // useCanvasPopupStatusController(6) - // const canvasPopupStatusState = useRecoilValue(canvasPopupStatusStore) - // if (Object.keys(canvasPopupStatusState[6]).length !== 0) { - // console.log('🚀 ~ useEffect ~ canvasPopupStatusState :', canvasPopupStatusState) - // } useEffect(() => { if (allocationType === 'auto') { - // 자동일 때 모듈의 회로 정보 초기화 + /** 자동일 때 모듈의 회로 정보 초기화 */ canvas .getObjects() .filter((obj) => obj.name === POLYGON_TYPE.MODULE) @@ -70,79 +69,103 @@ export default function StepUp(props) { canvas.renderAll() - // PCS 자동 승압설정 정보 조회 + /** PCS 자동 승압설정 정보 조회 */ fetchAutoStepUpData() } else { - // PCS 수동 승압설정 정보 조회 + /** PCS 수동 승압설정 정보 조회 */ fetchPassiStepUpData() } }, []) - // PCS 자동 승압설정 정보 조회 + /** + * PCS 자동 승압설정 정보 조회 + */ + + const isMultiOptions = () => { + return selectedModels.some((model) => model.pcsSerParallelYn === 'Y') + } + const fetchAutoStepUpData = async () => { try { const params = { - ...props.getOptYn(), // 옵션 Y/N - useModuleItemList: props.getUseModuleItemList(), // 사용된 모듈아이템 List - roofSurfaceList: props.getRoofSurfaceList(), // 지붕면 목록 - pcsItemList: props.getSelectedPcsItemList(), // PCS 아이템 목록 + ...props.getOptYn() /** 옵션 Y/N */, + useModuleItemList: props.getUseModuleItemList() /** 사용된 모듈아이템 List */, + roofSurfaceList: props.getRoofSurfaceList() /** 지붕면 목록 */, + pcsItemList: props.getSelectedPcsItemList() /** PCS 아이템 목록 */, } - - // 회로 구성 가능 여부 체크 통과 시 승압설정 정보 조회 + /** 회로 구성 가능 여부 체크 통과 시 승압설정 정보 조회 */ getPcsVoltageStepUpList(params).then((res) => { if (res?.result.resultCode === 'S' && res?.data) { const dataArray = Array.isArray(res.data) ? res.data : [res.data] const stepUpListData = formatStepUpListData(dataArray) - // PCS 승압설정 정보 SET + /** PCS 승압설정 정보 SET */ setStepUpListData(stepUpListData) - // PCS 옵션 조회 - const formattedOptCodes = formatOptionCodes(res.data.optionList) - setOptCodes(formattedOptCodes) - setSeletedOption(formattedOptCodes[0]) + /** PCS 옵션 조회 */ + // const formattedOptCodes = formatOptionCodes(res.data.optionList) + // setOptCodes(formattedOptCodes) + // setSeletedOption(formattedOptCodes[0]) - // 캔버스에 회로 정보 적용 - //stepUpListData[0].pcsItemList.forEach((pcsItem) => { - stepUpListData[0].pcsItemList.forEach((pcsItem) => { + /** 캔버스에 회로 정보 적용 */ + // 병설일때 pcs 있으면 setSubOpsions, 없으면 setMainOptions + console.log('stepUpListData', stepUpListData) + stepUpListData[0].pcsItemList.forEach((pcsItem, index) => { + const optionList = formatOptionCodes(pcsItem.optionList) + if (isMultiOptions()) { + if (index === 0) { + setMainOptions(optionList) + setSeletedMainOption(optionList[0]) + } else { + setSubOptions(optionList) + setSeletedSubOption(optionList[0]) + } + } else { + if (index === 0) { + setMainOptions(optionList) + setSeletedMainOption(optionList[0]) + } + } const selectedSerQty = pcsItem.serQtyList.find((serQty) => serQty.selected) if (selectedSerQty) { selectedSerQty.roofSurfaceList.forEach((roofSurface) => { const targetSurface = canvas.getObjects().filter((obj) => obj.id === roofSurface.roofSurfaceId)[0] const moduleIds = targetSurface.modules.map((module) => module.id) - // 기존 모듈 텍스트 삭제 + /** 기존 모듈 텍스트 삭제 */ canvas .getObjects() .filter((obj) => moduleIds.includes(obj.parentId)) .forEach((text) => canvas.remove(text)) - // 새로운 모듈 회로 정보 추가 + /** 새로운 모듈 회로 정보 추가 */ roofSurface.moduleList.forEach((module) => { - const targetModule = canvas.getObjects().filter((obj) => obj.id === module.uniqueId)[0] - const moduleCircuitText = new fabric.Text(module.circuit, { - left: targetModule.left + targetModule.width / 2, - top: targetModule.top + targetModule.height / 2, - fontFamily: circuitNumberText.fontFamily.value, - fontWeight: circuitNumberText.fontWeight.value.toLowerCase().includes('bold') ? 'bold' : 'normal', - fontStyle: circuitNumberText.fontWeight.value.toLowerCase().includes('italic') ? 'italic' : 'normal', - fontSize: circuitNumberText.fontSize.value, - fill: circuitNumberText.fontColor.value, - width: targetModule.width, - height: targetModule.height, - textAlign: 'center', - originX: 'center', - originY: 'center', - name: 'circuitNumber', - parentId: targetModule.id, - circuitInfo: module.pcsItemId, - selectable: false, - visible: isDisplayCircuitNumber, - }) - targetModule.circuit = moduleCircuitText - targetModule.pcsItemId = module.pcsItemId - targetModule.circuitNumber = module.circuit - canvas.add(moduleCircuitText) + const targetModule = canvas.getObjects().find((obj) => obj.id === module.uniqueId) + if (targetModule && module.circuit !== '' && module.circuit) { + const moduleCircuitText = new fabric.Text(module.circuit, { + left: targetModule.left + targetModule.width / 2, + top: targetModule.top + targetModule.height / 2, + fontFamily: circuitNumberText.fontFamily.value, + fontWeight: circuitNumberText.fontWeight.value.toLowerCase().includes('bold') ? 'bold' : 'normal', + fontStyle: circuitNumberText.fontWeight.value.toLowerCase().includes('italic') ? 'italic' : 'normal', + fontSize: circuitNumberText.fontSize.value, + fill: circuitNumberText.fontColor.value, + width: targetModule.width, + height: targetModule.height, + textAlign: 'center', + originX: 'center', + originY: 'center', + name: 'circuitNumber', + parentId: targetModule.id, + circuitInfo: module.pcsItemId, + selectable: false, + visible: isDisplayCircuitNumber, + }) + targetModule.circuit = moduleCircuitText + targetModule.pcsItemId = module.pcsItemId + targetModule.circuitNumber = module.circuit + canvas.add(moduleCircuitText) + } }) }) } @@ -152,10 +175,6 @@ export default function StepUp(props) { setModuleStatisticsData() } else { swalFire({ text: getMessage('common.message.send.error') }) - // swalFire({ - // title: res.result.resultMsg, - // type: 'alert', - // }) } }) } catch (error) { @@ -163,38 +182,34 @@ export default function StepUp(props) { } } - // PCS 수동 승압설정 정보 조회 + /** + * PCS 수동 승압설정 정보 조회 + */ const fetchPassiStepUpData = async () => { try { - // 1-1 2-2 - // canvas - // .getObjects() - // .filter((obj) => obj.name === POLYGON_TYPE.MODULE && obj.circuit) - // .map((module) => module.circuitNumber) - - // 모듈 데이터 가져오기 + /** 모듈 데이터 가져오기 */ const modules = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE) - // PCS별 회로 정보를 저장할 객체 + /** PCS별 회로 정보를 저장할 객체 */ const pcsSummary = {} - // 각 모듈을 순회하며 PCS별 회로 정보 수집 + /** 각 모듈을 순회하며 PCS별 회로 정보 수집 */ modules.forEach((module) => { if (!module.circuit || !module.pcsItemId) return - if (!pcsSummary[module.pcsItemId]) { - pcsSummary[module.pcsItemId] = { + if (!pcsSummary[module.circuit.circuitInfo.id]) { + pcsSummary[module.circuit.circuitInfo.id] = { circuits: {}, totalModules: 0, } } const circuitNumber = module.circuitNumber - if (!pcsSummary[module.pcsItemId].circuits[circuitNumber]) { - pcsSummary[module.pcsItemId].circuits[circuitNumber] = 0 + if (!pcsSummary[module.circuit.circuitInfo.id].circuits[circuitNumber]) { + pcsSummary[module.circuit.circuitInfo.id].circuits[circuitNumber] = 0 } - pcsSummary[module.pcsItemId].circuits[circuitNumber]++ - pcsSummary[module.pcsItemId].totalModules++ + pcsSummary[module.circuit.circuitInfo.id].circuits[circuitNumber]++ + pcsSummary[module.circuit.circuitInfo.id].totalModules++ }) const params = { @@ -202,20 +217,35 @@ export default function StepUp(props) { pcsItemList: getSelectedPcsItemList(), } - // PCS 접속함 및 옵션 목록 조회 + /** PCS 접속함 및 옵션 목록 조회 */ getPcsConnOptionItemList(params).then((res) => { if (res?.result.code === 200 && res?.data) { - // PCS 아이템 리스트에 serQtyList 추가 - const pcsItemListWithSerQty = res.data.pcsItemList.map((pcsItem) => { - const pcsData = pcsSummary[pcsItem.itemId] || { circuits: {}, totalModules: 0 } + /** PCS 아이템 리스트에 serQtyList 추가 */ + const pcsItemListWithSerQty = res.data.pcsItemList.map((pcsItem, index) => { + const pcsData = pcsSummary[selectedModels[index].id] || { circuits: {}, totalModules: 0 } const circuitCounts = Object.values(pcsData.circuits) + const optionList = formatOptionCodes(pcsItem.optionList) + if (isMultiOptions()) { + if (index === 0) { + setMainOptions(optionList) + setSeletedMainOption(optionList[0]) + } else { + setSubOptions(optionList) + setSeletedSubOption(optionList[0]) + } + } else { + if (index === 0) { + setMainOptions(optionList) + setSeletedMainOption(optionList[0]) + } + } return { ...pcsItem, serQtyList: [ { - // 한 회로당 최대 모듈 수 + /** 한 회로당 최대 모듈 수 */ serQty: circuitCounts.length > 0 ? Math.max(...circuitCounts) : 0, - // 회로 개수 + /** 회로 개수 */ paralQty: Object.keys(pcsData.circuits).length || 0, rmdYn: 'Y', usePossYn: 'Y', @@ -225,19 +255,19 @@ export default function StepUp(props) { } }) - // Update res.data with modified pcsItemList + /** res.data with modified pcsItemList */ res.data.pcsItemList = pcsItemListWithSerQty const dataArray = Array.isArray(res.data) ? res.data : [res.data] const stepUpListData = formatStepUpListData(dataArray) - // PCS 승압설정 정보 SET + /** PCS 승압설정 정보 SET */ setStepUpListData(stepUpListData) - // PCS 옵션 조회 - const formattedOptCodes = formatOptionCodes(res.data.optionList) - setOptCodes(formattedOptCodes) - setSeletedOption(formattedOptCodes[0]) + /** PCS 옵션 조회 */ + // const formattedOptCodes = formatOptionCodes(res.data.optionList) + // setOptCodes(formattedOptCodes) + // setSeletedOption(formattedOptCodes[0]) } }) } catch (error) { @@ -245,16 +275,20 @@ export default function StepUp(props) { } } - // PCS 옵션 조회 + /** + * PCS 옵션 조회 + */ const formatOptionCodes = (optionList = []) => { return optionList?.map((opt) => ({ - code: opt.pcsOptCd ? opt.pcsOptCd : '', - name: opt.pcsOptNm ? opt.pcsOptNm : '', - nameJp: opt.pcsOptNmJp ? opt.pcsOptNmJp : '', + code: opt.pcsOptCd ?? '', + name: opt.pcsOptNm ?? '', + nameJp: opt.pcsOptNmJp ?? '', })) } - // PCS 승압설정 정보 포맷 후 추천 값 저장 + /** + * PCS 승압설정 정보 포맷 후 추천 값 저장 + */ const formatStepUpListData = (dataArray = []) => { const formattedData = dataArray?.map((stepUps) => ({ ...stepUps, @@ -266,16 +300,20 @@ export default function StepUp(props) { return formattedData } - // PCS 옵션 포맷 + /** + * PCS 옵션 포맷 + */ const formatOptionList = (optionList = []) => { return optionList?.map((option) => ({ - pcsOptCd: option.pcsOptCd ? option.pcsOptCd : '', - pcsOptNm: option.pcsOptNm ? option.pcsOptNm : '', - pcsOptNmJp: option.pcsOptNmJp ? option.pcsOptNmJp : '', + pcsOptCd: option.pcsOptCd ?? '', + pcsOptNm: option.pcsOptNm ?? '', + pcsOptNmJp: option.pcsOptNmJp ?? '', })) } - // PCS 아이템 포맷 + /** + * PCS 아이템 포맷 + */ const formatPcsItemList = (pcsItemList = []) => { return pcsItemList?.map((item, index) => ({ goodsNo: item.goodsNo ? item.goodsNo : '', @@ -286,56 +324,68 @@ export default function StepUp(props) { uniqueIndex: `${item.itemId}_${index}`, // 고유 식별자 추가(동일한 PCS를 구분) connList: formatConnList(item.connList), serQtyList: formatSerQtyList(item.serQtyList), + optionList: item.optionList ?? [], })) } - // PCS 연결 포맷 + /** + * PCS 연결 포맷 + */ const formatConnList = (connList = []) => { if (!connList) return [] // null인 경우 빈 배열 반환 return connList?.map((conn) => ({ - connAllowCur: conn.connAllowCur ? conn.connAllowCur : 0, - connMaxParalCnt: conn.connMaxParalCnt ? conn.connMaxParalCnt : 0, - goodsNo: conn.goodsNo ? conn.goodsNo : '', - itemId: conn.itemId ? conn.itemId : '', - itemNm: conn.itemNm ? conn.itemNm : '', - vstuParalCnt: conn.vstuParalCnt ? conn.vstuParalCnt : 0, + connAllowCur: conn.connAllowCur ?? 0, + connMaxParalCnt: conn.connMaxParalCnt ?? 0, + goodsNo: conn.goodsNo ?? '', + itemId: conn.itemId ?? '', + itemNm: conn.itemNm ?? '', + vstuParalCnt: conn.vstuParalCnt ?? 0, })) } - // PCS 시리즈 포맷 + /** + * PCS 시리즈 포맷 + */ const formatSerQtyList = (serQtyList = []) => { return serQtyList?.map((qty) => ({ code: uuidv4(), - serQty: qty.serQty ? qty.serQty : 0, - paralQty: qty.paralQty ? qty.paralQty : 0, - rmdYn: qty.rmdYn ? qty.rmdYn : 'N', - usePossYn: qty.usePossYn ? qty.usePossYn : 'Y', + serQty: qty.serQty ?? 0, + paralQty: qty.paralQty ?? 0, + rmdYn: qty.rmdYn ?? 'N', + usePossYn: qty.usePossYn ?? 'Y', roofSurfaceList: formatRoofSurfaceList(qty.roofSurfaceList), selected: qty.rmdYn === 'Y', })) } - // PCS RoofSurface 포맷 + /** + * PCS RoofSurface 포맷 + */ const formatRoofSurfaceList = (roofSurfaceList = []) => { return roofSurfaceList?.map((rsf) => ({ moduleList: formatModuleList(rsf.moduleList), - roofSurface: rsf.roofSurface ? rsf.roofSurface : '', - roofSurfaceId: rsf.roofSurfaceId ? rsf.roofSurfaceId : '', - roofSurfaceIncl: rsf.roofSurfaceIncl ? rsf.roofSurfaceIncl : '', - })) - } - // PCS MatModule 포맷 - const formatModuleList = (moduleList = []) => { - return moduleList?.map((module) => ({ - circuit: module.circuit ? module.circuit : '', - itemId: module.itemId ? module.itemId : '', - pcsItemId: module.pcsItemId ? module.pcsItemId : '', - uniqueId: module.uniqueId ? module.uniqueId : '', + roofSurface: rsf.roofSurface ?? '', + roofSurfaceId: rsf.roofSurfaceId ?? '', + roofSurfaceIncl: rsf.roofSurfaceIncl ? +rsf.roofSurfaceIncl : '', })) } - // 각 모듈의 탭을 변경하는 함수 + /** + * PCS MatModule 포맷 + */ + const formatModuleList = (moduleList = []) => { + return moduleList?.map((module) => ({ + circuit: module.circuit ?? '', + itemId: module.itemId ?? '', + pcsItemId: module.pcsItemId ?? '', + uniqueId: module.uniqueId ?? '', + })) + } + + /** + * 각 모듈의 탭을 변경하는 함수 + */ const handleTabChange = (goodsNo, idx, tabNumber) => { setModuleTabs((prev) => ({ ...prev, @@ -343,9 +393,11 @@ export default function StepUp(props) { })) } - // 행 선택 핸들러 함수 추가 + /** + * 행 선택 핸들러 함수 추가 + */ const handleRowClick = (mainIdx, subIdx) => { - // 자동 승압 설정인 경우만 실행 + /** 자동 승압 설정인 경우만 실행 */ if (allocationType !== 'auto') return let tempStepUpListData = [...stepUpListData] @@ -357,26 +409,24 @@ export default function StepUp(props) { } item.selected = index === subIdx }) - // 선택된 행 정보 저장 + /** 선택된 행 정보 저장 */ setStepUpListData(tempStepUpListData) - // console.log('🚀 ~ handleRowClick ~ tempStepUpListData:', tempStepUpListData) - // console.log('🚀 ~ handleRowClick ~ selectedData:', selectedData) - - // PCS 2개 이상 또는 첫번째 PCS 선택 시에만 실행 - if (stepUpListData[0].pcsItemList.length > 1 && mainIdx === 0) { - // 파워컨디셔너 옵션 조회 요청 파라미터 + /** PCS 2개 이상 또는 첫번째 PCS 선택 시에만 실행 */ + if (tempStepUpListData[0].pcsItemList.length > 1 && mainIdx === 0) { + /** 파워컨디셔너 옵션 조회 요청 파라미터 */ const params = { ...props.getOptYn(), // 옵션 Y/N useModuleItemList: props.getUseModuleItemList(), // 사용된 모듈아이템 List roofSurfaceList: props.getRoofSurfaceList(), // 지붕면 목록 pcsItemList: props.getSelectedPcsItemList().map((pcsItem, index) => { - // PCS 아이템 목록 - // tempStepUpListData에서 해당 PCS 아이템 찾기 - // uniqueIndex를 사용하여 매칭 + /** PCS 아이템 목록 + * tempStepUpListData에서 해당 PCS 아이템 찾기 + * uniqueIndex를 사용하여 매칭 + */ const matchingPcsItem = tempStepUpListData[0].pcsItemList.find((item) => item.uniqueIndex === `${pcsItem.itemId}_${index}`) - // 선택된 serQty 찾기 + /** 선택된 serQty 찾기 */ const selectedSerQty = matchingPcsItem?.serQtyList.find((serQty) => serQty.selected)?.serQty || 0 return { @@ -386,34 +436,29 @@ export default function StepUp(props) { }), } - // PCS가 1개 이고 2번째 또는 3번째 PCS serQty가 0인 경우는 추천 API 실행하지 않음 + /** PCS가 1개 이고 2번째 또는 3번째 PCS serQty가 0인 경우는 추천 API 실행하지 않음 */ if (params.pcsItemList.length !== 1 && (params.pcsItemList[1]?.applySerQty !== 0 || params.pcsItemList[2]?.applySerQty) !== 0) { - // PCS 승압설정 정보 조회 - //const res = await getPcsVoltageStepUpList(params) - //getPcsManualConfChk(params).then((res) => { + /** PCS 승압설정 정보 조회 */ getPcsVoltageStepUpList(params).then((res) => { if (res?.result.resultCode === 'S' && res?.data) { const dataArray = Array.isArray(res.data) ? res.data : [res.data] const stepUpListData = formatStepUpListData(dataArray) - // PCS 승압설정 정보 SET + /** PCS 승압설정 정보 SET */ setStepUpListData(stepUpListData) - // PCS 옵션 조회 - const formattedOptCodes = formatOptionCodes(res.data.optionList) - setOptCodes(formattedOptCodes) - setSeletedOption(formattedOptCodes[0]) + /** PCS 옵션 조회 */ + // const formattedOptCodes = formatOptionCodes(res.data.optionList) + // setOptCodes(formattedOptCodes) + // setSeletedOption(formattedOptCodes[0]) } else { swalFire({ text: getMessage('common.message.send.error') }) - // swalFire({ - // title: res.result.resultMsg, - // type: 'alert', - // }) } }) } } + /** 모듈 목록 삭제 */ canvas .getObjects() .filter((obj) => obj.name === POLYGON_TYPE.MODULE) @@ -423,13 +468,14 @@ export default function StepUp(props) { module.pcsItemId = null }) + /** 선택된 모듈 목록 추가 */ selectedData.roofSurfaceList.forEach((roofSurface) => { const targetSurface = canvas.getObjects().filter((obj) => obj.id === roofSurface.roofSurfaceId)[0] const moduleIds = targetSurface.modules.map((module) => { return module.id }) - // 모듈 목록 삭제 + /** 모듈 목록 삭제 */ canvas .getObjects() .filter((obj) => moduleIds.includes(obj.parentId)) @@ -437,34 +483,35 @@ export default function StepUp(props) { canvas.remove(text) }) - // 모듈 목록 추가 + /** 모듈 목록 추가 */ canvas.renderAll() roofSurface.moduleList.forEach((module) => { - const targetModule = canvas.getObjects().filter((obj) => obj.id === module.uniqueId)[0] - if (module.circuit === '') return - const moduleCircuitText = new fabric.Text(module.circuit, { - left: targetModule.left + targetModule.width / 2, - top: targetModule.top + targetModule.height / 2, - fontFamily: circuitNumberText.fontFamily.value, - fontWeight: circuitNumberText.fontWeight.value.toLowerCase().includes('bold') ? 'bold' : 'normal', - fontStyle: circuitNumberText.fontWeight.value.toLowerCase().includes('italic') ? 'italic' : 'normal', - fontSize: circuitNumberText.fontSize.value, - fill: circuitNumberText.fontColor.value, - width: targetModule.width, - height: targetModule.height, - textAlign: 'center', - originX: 'center', - originY: 'center', - name: 'circuitNumber', - parentId: targetModule.id, - circuitInfo: module.pcsItemId, - visible: isDisplayCircuitNumber, - }) - targetModule.circuit = moduleCircuitText - targetModule.pcsItemId = module.pcsItemId - targetModule.circuitNumber = module.circuit - canvas.add(moduleCircuitText) + const targetModule = canvas.getObjects().find((obj) => obj.id === module.uniqueId) + if (targetModule && module.circuit !== '' && module.circuit !== null) { + const moduleCircuitText = new fabric.Text(module.circuit, { + left: targetModule.left + targetModule.width / 2, + top: targetModule.top + targetModule.height / 2, + fontFamily: circuitNumberText.fontFamily.value, + fontWeight: circuitNumberText.fontWeight.value.toLowerCase().includes('bold') ? 'bold' : 'normal', + fontStyle: circuitNumberText.fontWeight.value.toLowerCase().includes('italic') ? 'italic' : 'normal', + fontSize: circuitNumberText.fontSize.value, + fill: circuitNumberText.fontColor.value, + width: targetModule.width, + height: targetModule.height, + textAlign: 'center', + originX: 'center', + originY: 'center', + name: 'circuitNumber', + parentId: targetModule.id, + circuitInfo: module.pcsItemId, + visible: isDisplayCircuitNumber, + }) + targetModule.circuit = moduleCircuitText + targetModule.pcsItemId = module.pcsItemId + targetModule.circuitNumber = module.circuit + canvas.add(moduleCircuitText) + } }) }) @@ -472,7 +519,9 @@ export default function StepUp(props) { setModuleStatisticsData() } - // 현재 선택된 값들을 가져오는 함수 추가 + /** + * 현재 선택된 값들을 가져오는 함수 추가 + */ const getCurrentSelections = () => { const selectedValues = stepUpListData[0].pcsItemList.forEach((item) => { item.serQtyList.filter((serQty) => serQty.selected) @@ -493,20 +542,20 @@ export default function StepUp(props) { return selectedValues } - // props로 getCurrentSelections 함수 전달 + /** props로 getCurrentSelections 함수 전달 */ useEffect(() => { if (props.onInitialize) { props.onInitialize(getCurrentSelections) } }, []) - // stepUpListData가 변경될 때마다 업데이트하는 useEffect + /** stepUpListData가 변경될 때마다 업데이트하는 useEffect */ useEffect(() => { if (props.onInitialize) { - // onInitialize를 props에서 가져옴 + /** onInitialize를 props에서 가져옴 */ props.onInitialize(() => ({ ...getCurrentSelections(), - stepUpListData, // stepUpListData를 포함하여 반환 + stepUpListData /** stepUpListData를 포함하여 반환 */, })) } }, [stepUpListData]) @@ -515,15 +564,43 @@ export default function StepUp(props) { <>
    -
    +

    {getMessage('modal.circuit.trestle.setting.step.up.allocation.select.monitor')}

    +
    +
    + {mainOptions.length > 0 && ( + setSeletedMainOption(e)} + /> + )} +
    + {isMultiOptions() && selectedModels.length === 2 && ( +
    + {subOptions.length > 0 && ( + setSeletedSubOption(e)} + /> + )} +
    + )} +
    + + {/*
    {getMessage('modal.circuit.trestle.setting.step.up.allocation.select.monitor')} {optCodes.length > 0 && (
    - {/* */} { return { ...roof, name: globalLocale === 'ko' ? roof.name : roof.nameJp } })} @@ -536,7 +613,7 @@ export default function StepUp(props) { />
    )} -
    +
    */}
    @@ -625,8 +702,6 @@ export default function StepUp(props) { - {/* - */} diff --git a/src/components/floor-plan/modal/circuitTrestle/step/type/PassivityCircuitAllocation.jsx b/src/components/floor-plan/modal/circuitTrestle/step/type/PassivityCircuitAllocation.jsx index 6ec3ba25..e009a864 100644 --- a/src/components/floor-plan/modal/circuitTrestle/step/type/PassivityCircuitAllocation.jsx +++ b/src/components/floor-plan/modal/circuitTrestle/step/type/PassivityCircuitAllocation.jsx @@ -15,6 +15,7 @@ import { useRecoilState, useRecoilValue } from 'recoil' export default function PassivityCircuitAllocation(props) { const { + setTabNum, selectedModels, setSelectedModels, getOptYn: getApiProps, @@ -88,14 +89,14 @@ export default function PassivityCircuitAllocation(props) { ] if (!circuitNumber || circuitNumber === 0) { swalFire({ - text: '회로번호를 1 이상입력해주세요.', + text: getMessage('module.circuit.minimun.error'), type: 'alert', icon: 'warning', }) return } else if (targetModules.length === 0) { swalFire({ - text: '모듈을 선택해주세요.', + text: getMessage('module.not.found'), type: 'alert', icon: 'warning', }) @@ -113,7 +114,7 @@ export default function PassivityCircuitAllocation(props) { }) if (result) { swalFire({ - text: '회로 번호가 같은 다른 파워 컨디셔너 모듈이 있습니다. 다른 회로 번호를 설정하십시오.', + text: getMessage('module.already.exist.error'), type: 'alert', icon: 'warning', }) @@ -156,18 +157,10 @@ export default function PassivityCircuitAllocation(props) { obj.pcsItemCode = selectedPcs.id obj.circuit = moduleCircuitText obj.circuitNumber = getCircuitNumber() - tempSelectedPcs.used = true setSelectedPcs(tempSelectedPcs) canvas.add(moduleCircuitText) }) - let pcsList = JSON.parse(JSON.stringify(selectedModels)).map((model) => { - if (model.id === selectedPcs.id) { - model.isUsed = true - } - return model - }) - const roofSurfaceList = canvas .getObjects() .filter((obj) => POLYGON_TYPE.MODULE_SETUP_SURFACE === obj.name && obj?.modules.length > 0) @@ -175,7 +168,7 @@ export default function PassivityCircuitAllocation(props) { return { roofSurfaceId: surface.id, roofSurface: surface.direction, - roofSurfaceIncl: canvas.getObjects().filter((obj) => obj.id === surface.parentId)[0].pitch, + roofSurfaceIncl: +canvas.getObjects().filter((obj) => obj.id === surface.parentId)[0].pitch, moduleList: surface.modules.map((module) => { return { itemId: module.moduleInfo.itemId, @@ -185,9 +178,248 @@ export default function PassivityCircuitAllocation(props) { }), } }) + let pcsCount = {} + let result = {} + canvas + .getObjects() + .filter((obj) => obj.name === POLYGON_TYPE.MODULE) + .forEach((module) => { + if (module.circuitNumber) { + const circuitNumber = module.circuitNumber.replace(/[()]/g, '') + pcsCount[circuitNumber] = (pcsCount[circuitNumber] || 0) + 1 + } + }) + for (const key in pcsCount) { + const firstPart = key.split('-')[0] // '-' 기준으로 첫 번째 부분을 추출 + const value = pcsCount[key] - const usedPcses = pcsList.filter((model) => model.isUsed) - const pcsItemList = usedPcses.map((model, index) => { + // 그룹이 없으면 초기화 + if (!result[firstPart]) { + result[firstPart] = { maxValue: value, count: 1 } + } else { + // 이미 그룹이 있으면 큰 값으로 갱신, count는 증가 + result[firstPart].maxValue = Math.max(result[firstPart].maxValue, value) + result[firstPart].count += 1 + } + } + const pcsItemList = selectedModels.map((model, index) => { + return { + pcsMkrCd: model.pcsMkrCd, + pcsSerCd: model.pcsSerCd, + itemId: model.itemId, + itemNm: model.itemNm, + goodsNo: model.goodsNo, + serQtyList: [ + { + 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: roofSurfaceList, + }, + ], + } + }) + const params = { + ...getApiProps(), + useModuleItemList: getSelectedModuleList(), + pcsItemList: pcsItemList, + } + + getPcsManualConfChk(params).then((res) => { + if (res?.resultCode === 'E') { + swalFire({ + text: res.resultMsg, + type: 'alert', + icon: 'warning', + confirmFn: () => { + const circuitNumbers = canvas.getObjects().filter((obj) => obj.name === 'circuitNumber' && targetModules.includes(obj.parentId)) + canvas.remove(...circuitNumbers) + canvas + .getObjects() + .filter((obj) => obj.name === 'module' && targetModules.includes(obj.id)) + .forEach((obj) => { + obj.pcsItemId = null + obj.circuit = null + obj.circuitNumber = null + }) + canvas.renderAll() + }, + }) + setTargetModules([]) + return + } + + setTargetModules([]) + setCircuitNumber(+circuitNumber + 1) + setModuleStatisticsData() + }) + } + + const getCircuitNumber = () => { + if (selectedModels.length === 1) { + return `(${circuitNumber})` + } else { + return `(${selectedModels.findIndex((model) => model.id === selectedPcs.id) + 1}-${circuitNumber})` + } + } + + const initSelectedPcsCircuitNumber = () => { + swalFire({ + title: getMessage('modal.circuit.trestle.setting.circuit.allocation.passivity.selected.power.conditional.reset.info'), + type: 'confirm', + icon: 'warning', + confirmFn: () => { + const circuitModules = canvas.getObjects().filter((obj) => obj.name === 'module' && obj.circuit?.circuitInfo?.id === selectedPcs.id) + if (circuitModules.length === 0) { + return + } + const circuitNumbers = circuitModules.map((obj) => { + const circuitNumber = obj.circuitNumber.replace(/[()]/g, '').split('-') + return parseInt(circuitNumber[circuitNumber.length - 1]) + }) + const minCircuitNumber = Math.min(...circuitNumbers) + canvas.remove(...circuitModules.map((module) => module.circuit)) + circuitModules.forEach((obj) => { + obj.circuit = null + obj.circuitNumber = null + obj.pcsItemId = null + }) + setCircuitNumber(minCircuitNumber) + setTargetModules([]) + + canvas.renderAll() + canvas.discardActiveObject() + setModuleStatisticsData() + }, + }) + } + + const initAllPcsCircuitNumber = () => { + canvas.discardActiveObject() + swalFire({ + title: getMessage('modal.circuit.trestle.setting.circuit.allocation.passivity.all.power.conditional.reset.info'), + type: 'confirm', + icon: 'warning', + confirmFn: () => { + const circuitModules = canvas + .getObjects() + .filter((obj) => obj.name === 'module' && selectedModels.map((model) => model.id).includes(obj.circuit?.circuitInfo?.id)) + canvas.remove(...circuitModules.map((module) => module.circuit)) + circuitModules.forEach((obj) => { + obj.circuit = null + obj.circuitNumber = null + obj.pcsItemId = null + }) + canvas.renderAll() + setCircuitNumber(1) + setTargetModules([]) + setModuleStatisticsData() + }, + }) + } + + const onApply = () => { + let uniqueCircuitNumbers = [ + ...new Set( + canvas + .getObjects() + .filter((obj) => obj.name === POLYGON_TYPE.MODULE && obj.circuitNumber) + .map((obj) => obj.circuitNumber), + ), + ] + if (!circuitNumber || circuitNumber === 0) { + swalFire({ + text: getMessage('module.circuit.minimun.error'), + type: 'alert', + icon: 'warning', + }) + return + } else if (targetModules.length === 0) { + swalFire({ + text: getMessage('module.not.found'), + type: 'alert', + icon: 'warning', + }) + return + } else if (selectedModels.length > 1) { + let result = false + + uniqueCircuitNumbers.forEach((number) => { + if ( + number.split('-')[1] === circuitNumber + ')' && + number.split('-')[0] !== '(' + (selectedModels.findIndex((model) => model.id === selectedPcs.id) + 1) + ) { + result = true + } + }) + if (result) { + swalFire({ + text: getMessage('module.already.exist.error'), + type: 'alert', + icon: 'warning', + }) + return + } + } + + let tempSelectedPcs = { ...selectedPcs } + canvas.discardActiveObject() + canvas + .getObjects() + .filter((obj) => targetModules.includes(obj.id)) + .forEach((obj) => { + if (obj.circuit) { + canvas.remove(obj.circuit) + } + const moduleCircuitText = new fabric.Text(getCircuitNumber(), { + left: obj.left + obj.width / 2, + top: obj.top + obj.height / 2, + fontFamily: circuitNumberText.fontFamily.value, + fontWeight: circuitNumberText.fontWeight.value.toLowerCase().includes('bold') ? 'bold' : 'normal', + fontStyle: circuitNumberText.fontWeight.value.toLowerCase().includes('italic') ? 'italic' : 'normal', + fontSize: circuitNumberText.fontSize.value, + fill: circuitNumberText.fontColor.value, + width: obj.width, + height: obj.height, + textAlign: 'center', + originX: 'center', + originY: 'center', + name: 'circuitNumber', + selectable: false, + parentId: obj.id, + circuitInfo: selectedPcs, + visible: isDisplayCircuitNumber, + }) + obj.set({ + strokeWidth: 0.3, + }) + obj.pcsItemId = selectedPcs.itemId + obj.pcsItemCode = selectedPcs.id + obj.circuit = moduleCircuitText + obj.circuitNumber = getCircuitNumber() + setSelectedPcs(tempSelectedPcs) + canvas.add(moduleCircuitText) + }) + + const roofSurfaceList = canvas + .getObjects() + .filter((obj) => POLYGON_TYPE.MODULE_SETUP_SURFACE === obj.name && obj?.modules.length > 0) + .map((surface) => { + return { + roofSurfaceId: surface.id, + roofSurface: surface.direction, + roofSurfaceIncl: +canvas.getObjects().filter((obj) => obj.id === surface.parentId)[0].pitch, + moduleList: surface.modules.map((module) => { + return { + itemId: module.moduleInfo.itemId, + circuit: module.circuitNumber, + pcsItemId: module.pcsItemId, + } + }), + } + }) + const pcsItemList = selectedModels.map((model, index) => { return { pcsMkrCd: model.pcsMkrCd, pcsSerCd: model.pcsSerCd, @@ -232,73 +464,13 @@ export default function PassivityCircuitAllocation(props) { canvas.renderAll() }, }) - setSelectedPcs({ ...selectedPcs, used: false }) setTargetModules([]) return } - setSelectedModels(pcsList) - setTargetModules([]) - setCircuitNumber(+circuitNumber + 1) setModuleStatisticsData() - }) - } - - const getCircuitNumber = () => { - if (selectedModels.length === 1) { - return `(${circuitNumber})` - } else { - return `(${selectedModels.findIndex((model) => model.id === selectedPcs.id) + 1}-${circuitNumber})` - } - } - - const initSelectedPcsCircuitNumber = () => { - swalFire({ - title: getMessage('modal.circuit.trestle.setting.circuit.allocation.passivity.selected.power.conditional.reset.info'), - type: 'confirm', - icon: 'warning', - confirmFn: () => { - const circuitModules = canvas.getObjects().filter((obj) => obj.name === 'module' && obj.circuit?.circuitInfo?.id === selectedPcs.id) - const circuitNumbers = circuitModules.map((obj) => { - const circuitNumber = obj.circuitNumber.replace(/[()]/g, '').split('-') - return parseInt(circuitNumber[circuitNumber.length - 1]) - }) - const minCircuitNumber = Math.min(...circuitNumbers) - canvas.remove(...circuitModules.map((module) => module.circuit)) - circuitModules.forEach((obj) => { - obj.circuit = null - obj.pcsItemId = null - }) - setCircuitNumber(minCircuitNumber) - setTargetModules([]) - - canvas.renderAll() - canvas.discardActiveObject() - setModuleStatisticsData() - }, - }) - } - - const initAllPcsCircuitNumber = () => { - canvas.discardActiveObject() - swalFire({ - title: getMessage('modal.circuit.trestle.setting.circuit.allocation.passivity.all.power.conditional.reset.info'), - type: 'confirm', - icon: 'warning', - confirmFn: () => { - const circuitModules = canvas - .getObjects() - .filter((obj) => obj.name === 'module' && selectedModels.map((model) => model.id).includes(obj.circuit?.circuitInfo?.id)) - canvas.remove(...circuitModules.map((module) => module.circuit)) - circuitModules.forEach((obj) => { - obj.circuit = null - obj.pcsItemId = null - }) - canvas.renderAll() - setTargetModules([]) - setModuleStatisticsData() - }, + setTabNum(2) }) } @@ -326,8 +498,8 @@ export default function PassivityCircuitAllocation(props) { {header.map((header, i) => ( ))} diff --git a/src/components/floor-plan/modal/dimensionLine/DimensionLineSetting.jsx b/src/components/floor-plan/modal/dimensionLine/DimensionLineSetting.jsx index 1ec3684e..c2acc12d 100644 --- a/src/components/floor-plan/modal/dimensionLine/DimensionLineSetting.jsx +++ b/src/components/floor-plan/modal/dimensionLine/DimensionLineSetting.jsx @@ -7,6 +7,9 @@ import { contextPopupPositionState } from '@/store/popupAtom' import QSelectBox from '@/components/common/select/QSelectBox' import { canvasState, pitchTextSelector } from '@/store/canvasAtom' import { defaultSlope } from '@/store/commonAtom' +import { re } from 'mathjs' +import { basicSettingState } from '@/store/settingAtom' +import { getChonByDegree, getDegreeByChon } from '@/util/canvas-util' export default function DimensionLineSetting(props) { const contextPopupPosition = useRecoilValue(contextPopupPositionState) @@ -18,131 +21,186 @@ export default function DimensionLineSetting(props) { const SelectOption01 = defaultSlope const [basicLength, setBasicLength] = useState(0) const [slopeAble, setSlopeAble] = useState(false) + const basicSetting = useRecoilValue(basicSettingState) const changeSlopeRef = useRef() - - let slopeInput1, slopeInput2 + const [options, setOptions] = useState([]) + const [changeLength, setChangeLength] = useState(null) + const [selectedSlope1, setSelectedSlope1] = useState(null) + const [selectedSlope2, setSelectedSlope2] = useState(null) useEffect(() => { if (canvas) { const dimensionObject = canvas.getActiveObject() + console.log(dimensionObject) const id = dimensionObject.groupId - const textObj = dimensionObject._objects.filter((obj) => obj.name === 'dimensionLineText' && obj.id === id)[0] - setBasicLength(parseInt(textObj.text)) + const textObj = dimensionObject._objects.filter((obj) => obj.name === 'dimensionLineText' && obj.group.groupId === id)[0] + if (!textObj) return + // setBasicLength(parseInt(textObj.text)) + setBasicLength(+dimensionObject.length) + setSelectedSlope1(dimensionObject.angle1) + setSelectedSlope2(dimensionObject.angle2) + setSlopeAble(dimensionObject.slopeAble) } + if (basicSetting.roofAngleSet === 'slope') { + setOptions( + Array.from({ length: 21 }).map((_, index) => { + return { + name: index * 0.5, + value: index * 0.5, + } + }), + ) + } else { + setOptions( + Array.from({ length: 7 }).map((_, index) => { + return { + name: index * 5, + value: index * 5, + } + }), + ) + } return () => { setBasicLength(0) } }, []) - const handleChangeLength = () => { - const changeLength = changeSlopeRef.current + useEffect(() => { + // if (!slopeAble) { + // const dimensionObject = canvas.getActiveObject() + // dimensionObject.set({ + // angle1: null, + // angle2: null, + // }) + // } + }, [slopeAble]) + const handleChangeLength = () => { if (canvas) { const dimensionObject = canvas.getActiveObject() const id = dimensionObject.groupId - const textObj = dimensionObject._objects.filter((obj) => obj.name === 'dimensionLineText' && obj.id === id)[0] - let resultText = changeLength.value > 0 ? changeLength.value : '0' + const textObj = dimensionObject._objects.filter((obj) => obj.name === 'dimensionLineText' && obj.group.groupId === id)[0] + let resultText = +changeLength > 0 ? +changeLength : dimensionObject.length if (slopeAble) { - if (slopeInput1) { - resultText = calculateLength(basicLength, slopeInput1.angleValue).toFixed(0) - - if (slopeInput2) { - const length = calculateLength(basicLength, slopeInput1.angleValue, slopeInput2.angleValue) - resultText = length.toFixed(0) - } - } + resultText = !selectedSlope2 + ? calculateLength(resultText, selectedSlope1.value).toFixed(0) + : calculateLength(resultText, selectedSlope1.value, selectedSlope2.value).toFixed(0) } textObj.set({ text: String(resultText), }) + dimensionObject.set({ + length: +changeLength > 0 ? +changeLength : dimensionObject.length, + slopeAble: slopeAble, + angle1: selectedSlope1, + angle2: selectedSlope2, + }) + setBasicLength(resultText) + setChangeLength('') canvas.renderAll() } } - const handleSelectbox = (option, params) => { - const index = params.index - if (index === 1) slopeInput1 = option - if (index === 2) slopeInput2 = option - } - - function calculateLength(originalLength, angle) { - const angleInRadians = angle * (Math.PI / 180) - const result = Math.sqrt(Math.pow(originalLength * Math.tan(angleInRadians), 2) + Math.pow(originalLength, 2)) - return result - } - - function calculateLength(originalLength, angle1, angle2) { - const numerator = Math.sqrt(Math.pow(angle1, 2) + 100 + Math.pow((10 * angle1) / angle2, 2)) * originalLength - const denominator = Math.sqrt(Math.pow((10 * angle1) / angle2, 2) + 100) - const result = numerator / denominator - return result + const calculateLength = (originalLength, angle, angle1) => { + if (!angle1) { + const slope1 = basicSetting.roofAngleSet !== 'slope' ? getDegreeByChon(angle) : angle + const result = Math.sqrt(Math.pow(originalLength * Math.tan((getDegreeByChon(slope1) * Math.PI) / 180), 2) + Math.pow(originalLength, 2)) + console.log(result) + return result + } else { + const slope1 = basicSetting.roofAngleSet !== 'slope' ? getChonByDegree(angle) : angle + const slope2 = basicSetting.roofAngleSet !== 'slope' ? getChonByDegree(angle1 ?? 0) : angle1 + const numerator = Math.sqrt(Math.pow(slope1, 2) + 100 + Math.pow((10 * slope1) / slope2, 2)) * originalLength + const denominator = Math.sqrt(Math.pow((10 * slope1) / slope2, 2) + 100) + const result = numerator / denominator + return result + } } return ( - -
    -
    -

    {getMessage('contextmenu.display.edit')}

    -
    -
    -
    {getMessage('modal.display.edit.info')}
    -
    -
    -
    - {getMessage('modal.display.edit.before.length')} -
    - -
    -
    -
    -
    - {getMessage('modal.display.edit.after.length')} -
    - -
    -
    -
    -
    - setSlopeAble(!slopeAble)} /> - -
    -
    -
    -
    -
    {getMessage('modal.display.edit.input.slope')}
    -
    -
    - {getMessage('slope')} -
    - -
    - {pitchText} -
    -
    - {getMessage('slope')} -
    - -
    - {pitchText} -
    -
    -
    {getMessage('modal.display.edit.input.slope.info')}
    -
    -
    - -
    -
    -
    -
    +
    ) } diff --git a/src/components/floor-plan/modal/distance/Distance.jsx b/src/components/floor-plan/modal/distance/Distance.jsx index d37302b6..8ec3aed2 100644 --- a/src/components/floor-plan/modal/distance/Distance.jsx +++ b/src/components/floor-plan/modal/distance/Distance.jsx @@ -16,60 +16,52 @@ export default function Distance(props) { } return ( - -
    -
    -

    {getMessage('modal.distance')}

    - -
    -
    -
    -
    -
    -
    {getMessage('modal.distance.dual.point')}
    -
    -
    -
    - -
    - mm + + closePopup(id)} /> + +
    +
    +
    +
    {getMessage('modal.distance.dual.point')}
    +
    +
    +
    +
    + mm
    -
    -
    {getMessage('modal.distance.horizon')}
    -
    -
    -
    - -
    - mm +
    +
    +
    {getMessage('modal.distance.horizon')}
    +
    +
    +
    +
    + mm
    -
    -
    {getMessage('modal.distance.vertical')}
    -
    -
    -
    - -
    - mm +
    +
    +
    {getMessage('modal.distance.vertical')}
    +
    +
    +
    +
    + mm
    -
    - -
    -
    -
    +
    + +
    + ) } diff --git a/src/components/floor-plan/modal/eavesGable/EavesGableEdit.jsx b/src/components/floor-plan/modal/eavesGable/EavesGableEdit.jsx index 56e88ba8..a59f8f27 100644 --- a/src/components/floor-plan/modal/eavesGable/EavesGableEdit.jsx +++ b/src/components/floor-plan/modal/eavesGable/EavesGableEdit.jsx @@ -38,32 +38,24 @@ export default function EavesGableEdit({ id, pos = { x: 50, y: 230 } }) { } return ( - -
    -
    -

    {getMessage('modal.eaves.gable.edit')}

    - + + closePopup(id)} /> + +
    + {buttonMenu.map((item) => ( + + ))}
    -
    -
    - {buttonMenu.map((item) => ( - - ))} -
    -
    -
    {getMessage('setting')}
    - {type === TYPES.EAVES && } - {type === TYPES.GABLE && } - {type === TYPES.WALL_MERGE && } - {type === TYPES.SHED && } -
    +
    +
    {getMessage('setting')}
    + {type === TYPES.EAVES && } + {type === TYPES.GABLE && } + {type === TYPES.WALL_MERGE && } + {type === TYPES.SHED && }
    -
    -
    +
    ) } diff --git a/src/components/floor-plan/modal/flowDirection/FlowDirectionSetting.jsx b/src/components/floor-plan/modal/flowDirection/FlowDirectionSetting.jsx index 14c40310..910a2f02 100644 --- a/src/components/floor-plan/modal/flowDirection/FlowDirectionSetting.jsx +++ b/src/components/floor-plan/modal/flowDirection/FlowDirectionSetting.jsx @@ -63,121 +63,113 @@ export default function FlowDirectionSetting(props) { ) return ( - -
    -
    -

    {getMessage('modal.shape.flow.direction.setting')}

    - -
    -
    -
    -
    -
    {getMessage('modal.flow.direction.setting')}
    -
    {getMessage('modal.flow.direction.setting.info')}
    -
    -
    - {getMessage('commons.north')} - - {getMessage('commons.east')} - - {getMessage('commons.south')} - - {getMessage('commons.west')} - -
    + + closePopup(id)} /> + +
    +
    +
    {getMessage('modal.flow.direction.setting')}
    +
    {getMessage('modal.flow.direction.setting.info')}
    +
    +
    + {getMessage('commons.north')} + + {getMessage('commons.east')} + + {getMessage('commons.south')} + + {getMessage('commons.west')} +
    -
    -
    {getMessage('modal.module.basic.setting.orientation.setting')}
    -
    {getMessage('modal.shape.flow.direction.setting.orientation.setting.info')}
    -
    -
    - { - setCompasDeg(0) - setType(FLOW_DIRECTION_TYPE.EIGHT_AZIMUTH) - }} - /> - -
    -
    - { - setType(FLOW_DIRECTION_TYPE.EIGHT_AZIMUTH) - setSelectedOrientation(e) - setCompasDeg(e.value) - }} - showKey={'name'} - targetKey={'value'} - sourceKey={'value'} - /> -
    +
    +
    +
    {getMessage('modal.module.basic.setting.orientation.setting')}
    +
    {getMessage('modal.shape.flow.direction.setting.orientation.setting.info')}
    +
    +
    + { + setCompasDeg(0) + setType(FLOW_DIRECTION_TYPE.EIGHT_AZIMUTH) + }} + /> +
    -
    -
    - { - setType(FLOW_DIRECTION_TYPE.TWENTY_FOUR_AZIMUTH) - }} - /> - -
    +
    + { + setType(FLOW_DIRECTION_TYPE.EIGHT_AZIMUTH) + setSelectedOrientation(e) + setCompasDeg(e.value) + }} + showKey={'name'} + targetKey={'value'} + sourceKey={'value'} + />
    -
    -
    -
    - {Array.from({ length: 180 / 15 + 1 }).map((dot, index) => ( -
    { - setType(FLOW_DIRECTION_TYPE.TWENTY_FOUR_AZIMUTH) - setCompasDeg(15 * (12 + index)) - }} - >
    - ))} - {Array.from({ length: 180 / 15 - 1 }).map((dot, index) => ( -
    { - setType(FLOW_DIRECTION_TYPE.TWENTY_FOUR_AZIMUTH) - setCompasDeg(15 * (index + 1)) - }} - >
    - ))} -
    -
    -
    +
    +
    +
    + { + setType(FLOW_DIRECTION_TYPE.TWENTY_FOUR_AZIMUTH) + }} + /> + +
    +
    +
    +
    +
    + {Array.from({ length: 180 / 15 + 1 }).map((dot, index) => ( +
    { + setType(FLOW_DIRECTION_TYPE.TWENTY_FOUR_AZIMUTH) + setCompasDeg(15 * (12 + index)) + }} + >
    + ))} + {Array.from({ length: 180 / 15 - 1 }).map((dot, index) => ( +
    { + setType(FLOW_DIRECTION_TYPE.TWENTY_FOUR_AZIMUTH) + setCompasDeg(15 * (index + 1)) + }} + >
    + ))} +
    +
    -
    - -
    -
    -
    +
    + +
    + ) } diff --git a/src/components/floor-plan/modal/grid/DotLineGrid.jsx b/src/components/floor-plan/modal/grid/DotLineGrid.jsx index 26b5f84c..d118188d 100644 --- a/src/components/floor-plan/modal/grid/DotLineGrid.jsx +++ b/src/components/floor-plan/modal/grid/DotLineGrid.jsx @@ -177,123 +177,115 @@ export default function DotLineGrid(props) { } return ( - -
    -
    -

    {getMessage('modal.canvas.setting.grid.dot.line.setting')}

    - +
    -
    -
    -
    - - -
    -
    - - -
    -
    -
    -
    -
    - - -
    -
    - {getMessage('modal.canvas.setting.grid.dot.line.setting.horizon')} -
    - onlyNumberInputChange(e, changeInput)} - /> -
    - mm -
    -
    - {getMessage('modal.canvas.setting.grid.dot.line.setting.vertical')} -
    - onlyNumberInputChange(e, changeInput)} - /> -
    - mm -
    -
    -
    -
    - - -
    -
    - {getMessage('modal.canvas.setting.grid.dot.line.setting.ratio')} -
    - onlyNumberInputChange(e, changeInput)} - /> -
    - mm -
    -
    - {selectOption && ( - - )} -
    -
    -
    -
    - - -
    -
    -
    -
    +
    ) } diff --git a/src/components/floor-plan/modal/grid/GridCopy.jsx b/src/components/floor-plan/modal/grid/GridCopy.jsx index 0d34b3d4..e1a6f9f9 100644 --- a/src/components/floor-plan/modal/grid/GridCopy.jsx +++ b/src/components/floor-plan/modal/grid/GridCopy.jsx @@ -20,65 +20,57 @@ export default function GridCopy(props) { copy(currentObject, ['↑', '←'].includes(arrow) ? +length * -1 : +length) } return ( - -
    -
    -

    {getMessage('modal.grid.copy')}

    - -
    -
    -
    {getMessage('modal.grid.copy.info')}
    -
    -
    -
    - {getMessage('modal.grid.copy.length')} -
    - setLength(e.target.value)} /> -
    - mm -
    -
    - - - - + + closePopup(id)} /> + +
    {getMessage('modal.grid.copy.info')}
    +
    +
    +
    + {getMessage('modal.grid.copy.length')} +
    + setLength(e.target.value)} />
    + mm +
    +
    + + + +
    -
    - -
    -
    -
    +
    + +
    + ) } diff --git a/src/components/floor-plan/modal/grid/GridMove.jsx b/src/components/floor-plan/modal/grid/GridMove.jsx index 1713647b..4aa27851 100644 --- a/src/components/floor-plan/modal/grid/GridMove.jsx +++ b/src/components/floor-plan/modal/grid/GridMove.jsx @@ -73,91 +73,83 @@ export default function GridMove(props) { closePopup(id) } return ( - -
    -
    -

    {getMessage('modal.grid.move')}

    - -
    -
    -
    {getMessage('modal.grid.move.info')}
    -
    -
    - setIsAll(!isAll)} /> - -
    -
    -
    -

    {getMessage('modal.grid.move.length')}

    -
    -
    - setVerticalSize(e.target.value)} - readOnly={!isAll && currentObject?.direction === 'vertical'} - /> -
    - mm -
    - - -
    + + handleClose()} /> + +
    {getMessage('modal.grid.move.info')}
    +
    +
    + setIsAll(!isAll)} /> + +
    +
    +
    +

    {getMessage('modal.grid.move.length')}

    +
    +
    + setVerticalSize(e.target.value)} + readOnly={!isAll && currentObject?.direction === 'vertical'} + />
    -
    -
    - setHorizonSize(e.target.value)} - readOnly={!isAll && currentObject?.direction === 'horizontal'} - /> -
    - mm -
    - - -
    + mm +
    + + +
    +
    +
    +
    + setHorizonSize(e.target.value)} + readOnly={!isAll && currentObject?.direction === 'horizontal'} + /> +
    + mm +
    + +
    -
    - -
    -
    -
    +
    + +
    +
    ) } diff --git a/src/components/floor-plan/modal/lineProperty/LinePropertySetting.jsx b/src/components/floor-plan/modal/lineProperty/LinePropertySetting.jsx index 74a67576..049c2e40 100644 --- a/src/components/floor-plan/modal/lineProperty/LinePropertySetting.jsx +++ b/src/components/floor-plan/modal/lineProperty/LinePropertySetting.jsx @@ -50,49 +50,41 @@ export default function LinePropertySetting(props) { } return ( - -
    -
    -

    {getMessage('contextmenu.line.property.edit')}

    - + + handleClosePopup()} /> + +
    + {getMessage('modal.line.property.edit.info')} + + {getMessage('modal.line.property.edit.selected')} [ {selectedProperty?.name} ] +
    -
    -
    - {getMessage('modal.line.property.edit.info')} - - {getMessage('modal.line.property.edit.selected')} [ {selectedProperty?.name} ] - -
    -
    -
    {getMessage('setting')}
    -
    -
    - {properties.map((property, index) => { - return ( -
    - = 10 ? index + 1 : `0${index + 1}`)} - onChange={(e) => setSelectedProperty(property)} - /> - -
    - ) - })} -
    +
    +
    {getMessage('setting')}
    +
    +
    + {properties.map((property, index) => { + return ( +
    + = 10 ? index + 1 : `0${index + 1}`)} + onChange={(e) => setSelectedProperty(property)} + /> + +
    + ) + })}
    -
    - -
    -
    -
    +
    + +
    + ) } diff --git a/src/components/floor-plan/modal/module/CircuitNumberEdit.jsx b/src/components/floor-plan/modal/module/CircuitNumberEdit.jsx index 62a0baaf..1e1b2f2f 100644 --- a/src/components/floor-plan/modal/module/CircuitNumberEdit.jsx +++ b/src/components/floor-plan/modal/module/CircuitNumberEdit.jsx @@ -14,36 +14,28 @@ export default function CircuitNumberEdit(props) { closePopup(id) } return ( - -
    -
    -

    {getMessage('modal.module.circuit.number.edit')}

    - -
    -
    -
    {getMessage('modal.module.circuit.number.edit.info')}
    -
    -
    -
    - - {getMessage('modal.module.circuit.number')} - -
    - -
    + + closePopup(id)} /> + +
    {getMessage('modal.module.circuit.number.edit.info')}
    +
    +
    +
    + + {getMessage('modal.module.circuit.number')} + +
    +
    -
    - -
    -
    -
    +
    + +
    + ) } diff --git a/src/components/floor-plan/modal/module/PanelEdit.jsx b/src/components/floor-plan/modal/module/PanelEdit.jsx index bfff66a2..2a06e062 100644 --- a/src/components/floor-plan/modal/module/PanelEdit.jsx +++ b/src/components/floor-plan/modal/module/PanelEdit.jsx @@ -9,7 +9,6 @@ import { deepCopyArray } from '@/util/common-utils' import { canvasState } from '@/store/canvasAtom' import * as turf from '@turf/turf' import { POLYGON_TYPE } from '@/common/common' -import { useModal } from '@nextui-org/react' import { useModule } from '@/hooks/module/useModule' import { useSwal } from '@/hooks/useSwal' @@ -34,7 +33,6 @@ export default function PanelEdit(props) { const canvas = useRecoilValue(canvasState) const { swalFire } = useSwal() const { moduleMove, moduleCopy, moduleMultiMove, moduleMultiCopy, moduleMoveAll, moduleCopyAll } = useModule() - useEffect(() => { if (!canvas) { const isSetupModules = canvas.getObjects().filter((obj) => obj.name === 'module') // selectedObj에 없는 객체만 필터링 @@ -52,7 +50,6 @@ export default function PanelEdit(props) { }) return } - debugger const completeSurfaces = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE && obj.isComplete) if (completeSurfaces.length > 0) { @@ -94,65 +91,64 @@ export default function PanelEdit(props) { } return ( - -
    -
    -

    - {getMessage([PANEL_EDIT_TYPE.MOVE, PANEL_EDIT_TYPE.COLUMN_MOVE].includes(type) ? 'modal.move.setting' : 'modal.copy.setting')}{' '} -

    - + + closePopup(id)} + /> + +
    + {getMessage( + [PANEL_EDIT_TYPE.MOVE, PANEL_EDIT_TYPE.MOVE_ALL, PANEL_EDIT_TYPE.COLUMN_MOVE].includes(type) + ? 'modal.move.setting.info' + : 'modal.copy.setting.info', + )}
    -
    -
    - {getMessage([PANEL_EDIT_TYPE.MOVE, PANEL_EDIT_TYPE.COLUMN_MOVE].includes(type) ? 'modal.move.setting.info' : 'modal.copy.setting.info')} -
    -
    -
    -
    - {getMessage('margin')} -
    - setLength(e.target.value)} /> -
    - mm -
    -
    - - - - +
    +
    +
    + {getMessage('margin')} +
    + setLength(e.target.value)} />
    + mm +
    +
    + + + +
    -
    - -
    -
    -
    +
    + +
    + ) } diff --git a/src/components/floor-plan/modal/module/column/ColumnInsert.jsx b/src/components/floor-plan/modal/module/column/ColumnInsert.jsx index 03b5b4e0..0c160656 100644 --- a/src/components/floor-plan/modal/module/column/ColumnInsert.jsx +++ b/src/components/floor-plan/modal/module/column/ColumnInsert.jsx @@ -24,89 +24,69 @@ export default function ColumnInsert(props) { } return ( - -
    -
    -

    {getMessage('modal.panel.column.insert')}

    -
    -
    -
    -
    {getMessage('modal.panel.column.insert.info')}
    -
    -
    -
    - - -
    -
    - - -
    -
    -
    - {selectedType === MODULE_INSERT_TYPE.LEFT && ( - - )} - {selectedType === MODULE_INSERT_TYPE.RIGHT && ( - - )} -
    -
    -
    -
    -
    {getMessage('legend')}
    -
    -
    -
    -
    - - {getMessage('modal.panel.select.column')} -
    -
    - - {getMessage('modal.panel.insert.column')} -
    -
    -
    -
    -
    -
    - -
    -
    -
    -
    +
    ) } diff --git a/src/components/floor-plan/modal/module/column/ColumnRemove.jsx b/src/components/floor-plan/modal/module/column/ColumnRemove.jsx index 95cdd942..b9079642 100644 --- a/src/components/floor-plan/modal/module/column/ColumnRemove.jsx +++ b/src/components/floor-plan/modal/module/column/ColumnRemove.jsx @@ -21,102 +21,69 @@ export default function ColumnRemove(props) { { name: getMessage('modal.panel.column.remove.type.none'), value: MODULE_REMOVE_TYPE.NONE }, ] const handleApply = () => { - // if (apply) apply() moduleColumnRemove(selectedType) closePopup(id) } return ( - -
    -
    -

    {getMessage('modal.panel.column.remove')}

    - -
    -
    -
    -
    {getMessage('modal.panel.column.remove.info')}
    -
    -
    - {types.map((type, index) => { - return ( -
    - setSelectedType(e.target.value)} - value={type.value} - checked={selectedType === type.value} - /> - -
    - ) - })} -
    -
    - {selectedType === MODULE_REMOVE_TYPE.LEFT && ( - - )} - {selectedType === MODULE_REMOVE_TYPE.RIGHT && ( - - )} - {selectedType === MODULE_REMOVE_TYPE.HORIZONTAL_SIDE && ( - - )} - {selectedType === MODULE_REMOVE_TYPE.NONE && ( - - )} -
    + + closePopup(id)} /> + +
    +
    {getMessage('modal.panel.column.remove.info')}
    +
    +
    + {types.map((type, index) => { + return ( +
    + setSelectedType(e.target.value)} + value={type.value} + checked={selectedType === type.value} + /> + +
    + ) + })} +
    +
    + {selectedType === MODULE_REMOVE_TYPE.LEFT && ( + + )} + {selectedType === MODULE_REMOVE_TYPE.RIGHT && ( + + )} + {selectedType === MODULE_REMOVE_TYPE.HORIZONTAL_SIDE && ( + + )} + {selectedType === MODULE_REMOVE_TYPE.NONE && ( + + )}
    -
    -
    {getMessage('legend')}
    -
    -
    -
    -
    - - {getMessage('modal.panel.select.column')} -
    +
    +
    +
    {getMessage('legend')}
    +
    +
    +
    +
    + + {getMessage('modal.panel.select.column')}
    -
    - -
    -
    -
    +
    + +
    + ) } diff --git a/src/components/floor-plan/modal/module/row/RowInsert.jsx b/src/components/floor-plan/modal/module/row/RowInsert.jsx index fa3c2fff..e9fb799c 100644 --- a/src/components/floor-plan/modal/module/row/RowInsert.jsx +++ b/src/components/floor-plan/modal/module/row/RowInsert.jsx @@ -24,89 +24,82 @@ export default function RowInsert(props) { } return ( - -
    -
    -

    {getMessage('modal.row.insert')}

    -
    -
    -
    -
    {getMessage('modal.row.insert.info')}
    -
    -
    -
    - - -
    -
    - - -
    -
    -
    - {selectedType === MODULE_INSERT_TYPE.TOP && ( - - )} - {selectedType === MODULE_INSERT_TYPE.BOTTOM && ( - - )} -
    -
    -
    -
    -
    {getMessage('legend')}
    -
    -
    -
    -
    - - {getMessage('modal.panel.select.row')} -
    -
    - - {getMessage('modal.panel.insert.row')} -
    -
    -
    -
    -
    -
    - -
    -
    -
    +
    ) } diff --git a/src/components/floor-plan/modal/module/row/RowRemove.jsx b/src/components/floor-plan/modal/module/row/RowRemove.jsx index 70c57c24..5cf95b3f 100644 --- a/src/components/floor-plan/modal/module/row/RowRemove.jsx +++ b/src/components/floor-plan/modal/module/row/RowRemove.jsx @@ -27,96 +27,88 @@ export default function RowRemove(props) { } return ( - -
    -
    -

    {getMessage('modal.row.remove')}

    - -
    -
    -
    -
    {getMessage('modal.row.remove.info')}
    -
    -
    - {types.map((type, index) => { - return ( -
    - setSelectedType(e.target.value)} - value={type.value} - checked={selectedType === type.value} - /> - -
    - ) - })} -
    -
    - {selectedType === MODULE_REMOVE_TYPE.TOP && ( - - )} - {selectedType === MODULE_REMOVE_TYPE.BOTTOM && ( - - )} - {selectedType === MODULE_REMOVE_TYPE.VERTICAL_SIDE && ( - - )} - {selectedType === MODULE_REMOVE_TYPE.NONE && ( - - )} -
    + + closePopup(id)} /> + +
    +
    {getMessage('modal.row.remove.info')}
    +
    +
    + {types.map((type, index) => { + return ( +
    + setSelectedType(e.target.value)} + value={type.value} + checked={selectedType === type.value} + /> + +
    + ) + })} +
    +
    + {selectedType === MODULE_REMOVE_TYPE.TOP && ( + + )} + {selectedType === MODULE_REMOVE_TYPE.BOTTOM && ( + + )} + {selectedType === MODULE_REMOVE_TYPE.VERTICAL_SIDE && ( + + )} + {selectedType === MODULE_REMOVE_TYPE.NONE && ( + + )}
    -
    -
    {getMessage('legend')}
    -
    -
    -
    -
    - - {getMessage('modal.panel.select.row')} -
    +
    +
    +
    {getMessage('legend')}
    +
    +
    +
    +
    + + {getMessage('modal.panel.select.row')}
    -
    - -
    -
    -
    +
    + +
    + ) } diff --git a/src/components/floor-plan/modal/movement/MovementSetting.jsx b/src/components/floor-plan/modal/movement/MovementSetting.jsx index 057d7d37..46464538 100644 --- a/src/components/floor-plan/modal/movement/MovementSetting.jsx +++ b/src/components/floor-plan/modal/movement/MovementSetting.jsx @@ -16,34 +16,26 @@ export default function MovementSetting({ id, pos = { x: 50, y: 230 } }) { } return ( - -
    -
    -

    {getMessage('plan.menu.roof.cover.movement.shape.updown')}

    - + ))} +
    +
    + {type === TYPE.FLOW_LINE && } + {type === TYPE.UP_DOWN && } +
    +
    +
    -
    -
    - {buttonType.map((item) => ( - - ))} -
    -
    - {type === TYPE.FLOW_LINE && } - {type === TYPE.UP_DOWN && } -
    -
    - -
    -
    -
    -
    +
    ) } diff --git a/src/components/floor-plan/modal/object/DormerOffset.jsx b/src/components/floor-plan/modal/object/DormerOffset.jsx index a1534891..af0ee8e0 100644 --- a/src/components/floor-plan/modal/object/DormerOffset.jsx +++ b/src/components/floor-plan/modal/object/DormerOffset.jsx @@ -32,79 +32,71 @@ export default function DormerOffset(props) { dormerOffset(arrow1, arrow2, length1, length2) - setArrow1(null) - setArrow2(null) - arrow1LengthRef.current.value = '' - arrow2LengthRef.current.value = '' + // setArrow1(null) + // setArrow2(null) + // arrow1LengthRef.current.value = '' + // arrow2LengthRef.current.value = '' // closePopup(id) } return ( - -
    -
    -

    {title}

    - -
    -
    -
    {getMessage('modal.dormer.offset.info')}
    -
    -
    -
    -

    {getMessage('length')}

    -
    -
    - -
    - mm -
    - - -
    + + closePopup(id)} /> + +
    {getMessage('modal.dormer.offset.info')}
    +
    +
    +
    +

    {getMessage('length')}

    +
    +
    +
    -
    -
    - -
    - mm -
    - - -
    + mm +
    + + +
    +
    +
    +
    + +
    + mm +
    + +
    -
    - -
    -
    -
    +
    + +
    +
    ) } diff --git a/src/components/floor-plan/modal/object/ObjectSetting.jsx b/src/components/floor-plan/modal/object/ObjectSetting.jsx index 69c4232c..1bbddfe6 100644 --- a/src/components/floor-plan/modal/object/ObjectSetting.jsx +++ b/src/components/floor-plan/modal/object/ObjectSetting.jsx @@ -24,7 +24,6 @@ export default function ObjectSetting({ id, pos = { x: 50, y: 230 } }) { const { closePopup } = usePopup() const surfaceShapePolygons = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF) - //오브젝트 배치로 넘어오면 면형상 선택 불가 useEffect(() => { canvas.discardActiveObject() @@ -54,15 +53,41 @@ export default function ObjectSetting({ id, pos = { x: 50, y: 230 } }) { const applyObject = () => { if (surfaceShapePolygons.length === 0) { - swalFire({ text: '지붕이 없어요 지붕부터 그리세요', icon: 'error' }) + swalFire({ text: getMessage('batch.object.outside.roof'), icon: 'error' }) return } //개구배치, 그림자배치 if (buttonAct === 1 || buttonAct === 2) { - applyOpeningAndShadow(objectPlacement, buttonAct, surfaceShapePolygons) + applyOpeningAndShadow(objectPlacement, buttonAct) } else { - applyDormers(dormerPlacement, buttonAct, surfaceShapePolygons) + const height = dormerPlacement.heightRef.current !== null ? dormerPlacement.heightRef.current.value / 10 : 0 + const width = dormerPlacement.widthRef.current !== null ? dormerPlacement.widthRef.current.value / 10 : 0 //triangle일때는 없음 + const pitch = dormerPlacement.pitchRef.current !== null ? Number(dormerPlacement.pitchRef.current.value) : 0 + const offsetRef = + dormerPlacement.offsetRef.current !== null + ? dormerPlacement.offsetRef.current.value === '' + ? 0 + : parseInt(dormerPlacement.offsetRef.current.value) / 10 + : 0 + const offsetWidthRef = + dormerPlacement.offsetWidthRef.current !== null + ? dormerPlacement.offsetWidthRef.current.value === '' + ? 0 + : parseInt(dormerPlacement.offsetWidthRef.current.value) / 10 + : 0 + const directionRef = dormerPlacement.directionRef.current + + const dormerParams = { + height: height, + width: width, + pitch: pitch, + offsetRef: offsetRef, + offsetWidthRef: offsetWidthRef, + directionRef: directionRef, + } + + applyDormers(dormerParams, buttonAct) } setIsHidden(true) } @@ -75,41 +100,33 @@ export default function ObjectSetting({ id, pos = { x: 50, y: 230 } }) { ] return ( - -
    -
    -

    {getMessage('plan.menu.placement.surface.object')}

    - + ))} +
    +
    + {buttonAct === 1 && } + {buttonAct === 2 && } + {buttonAct === 3 && } + {buttonAct === 4 && } +
    +
    +
    -
    -
    - {buttonMenu.map((item) => ( - - ))} -
    -
    - {buttonAct === 1 && } - {buttonAct === 2 && } - {buttonAct === 3 && } - {buttonAct === 4 && } -
    -
    - -
    -
    -
    -
    +
    ) } diff --git a/src/components/floor-plan/modal/object/RoofMaterialSetting.jsx b/src/components/floor-plan/modal/object/RoofMaterialSetting.jsx index 815175ce..27c06593 100644 --- a/src/components/floor-plan/modal/object/RoofMaterialSetting.jsx +++ b/src/components/floor-plan/modal/object/RoofMaterialSetting.jsx @@ -21,26 +21,18 @@ export default function RoofMaterialSetting(props) { ] return ( - -
    -
    -

    {getMessage('modal.roof.material.edit')}

    - -
    -
    -
    -
    - -
    -
    -
    - + + closePopup(id)} /> + +
    +
    +
    -
    -
    +
    + +
    + ) } diff --git a/src/components/floor-plan/modal/object/SizeSetting.jsx b/src/components/floor-plan/modal/object/SizeSetting.jsx index b7df4986..c5873006 100644 --- a/src/components/floor-plan/modal/object/SizeSetting.jsx +++ b/src/components/floor-plan/modal/object/SizeSetting.jsx @@ -32,71 +32,58 @@ export default function SizeSetting(props) { const width = widthRef.current.value const height = heightRef.current.value - if ( - target.name === BATCH_TYPE.OPENING || - target.name === BATCH_TYPE.SHADOW || - target.name === BATCH_TYPE.TRIANGLE_DORMER || - target.name === BATCH_TYPE.PENTAGON_DORMER - ) { - resizeObjectBatch(settingTarget, target, width, height) + if (target.name === BATCH_TYPE.OPENING || target.name === BATCH_TYPE.SHADOW) { + resizeObjectBatch(settingTarget, target, width, height, id) } else if (target.name === POLYGON_TYPE.ROOF) { - resizeSurfaceShapeBatch(settingTarget, target, width, height) + resizeSurfaceShapeBatch(settingTarget, target, width, height, id) } } return ( - -
    -
    -

    {getMessage('modal.size.setting')}

    - -
    -
    -
    -
    + + closePopup(id)} /> + +
    +
    +
    +
    + + mm +
    +
    + + mm +
    +
    +
    +
    +
    - + mm
    - + mm
    -
    -
    -
    -
    - - mm -
    -
    - - mm -
    -
    -
    -
    - - - - -
    -
    +
    + + + + +
    -
    - -
    -
    -
    +
    + +
    +
    ) } diff --git a/src/components/floor-plan/modal/object/type/PentagonDormer.jsx b/src/components/floor-plan/modal/object/type/PentagonDormer.jsx index 0bca7527..9d82485c 100644 --- a/src/components/floor-plan/modal/object/type/PentagonDormer.jsx +++ b/src/components/floor-plan/modal/object/type/PentagonDormer.jsx @@ -23,7 +23,10 @@ const PentagonDormer = forwardRef((props, refs) => {
    -
    {getMessage('modal.object.setting.agreement.depth')}
    +
    + + {getMessage('modal.object.setting.agreement.depth')} +
    @@ -45,7 +48,10 @@ const PentagonDormer = forwardRef((props, refs) => {
    -
    {getMessage('width')}
    +
    + + {getMessage('modal.object.setting.size.width')} +
    @@ -67,7 +73,7 @@ const PentagonDormer = forwardRef((props, refs) => {
    -
    {getMessage('slope')}
    +
    {getMessage('modal.object.setting.offset.slope')}
    diff --git a/src/components/floor-plan/modal/object/type/TriangleDormer.jsx b/src/components/floor-plan/modal/object/type/TriangleDormer.jsx index 229043c8..65fed20b 100644 --- a/src/components/floor-plan/modal/object/type/TriangleDormer.jsx +++ b/src/components/floor-plan/modal/object/type/TriangleDormer.jsx @@ -23,7 +23,10 @@ const TriangleDormer = forwardRef((props, refs) => {
    -
    {getMessage('modal.object.setting.agreement.depth')}
    +
    + + {getMessage('modal.object.setting.agreement.depth')} +
    @@ -45,7 +48,7 @@ const TriangleDormer = forwardRef((props, refs) => {
    -
    {getMessage('slope')}
    +
    {getMessage('modal.object.setting.offset.slope')}
    diff --git a/src/components/floor-plan/modal/outerlinesetting/PropertiesSetting.jsx b/src/components/floor-plan/modal/outerlinesetting/PropertiesSetting.jsx index 86724267..18b82edf 100644 --- a/src/components/floor-plan/modal/outerlinesetting/PropertiesSetting.jsx +++ b/src/components/floor-plan/modal/outerlinesetting/PropertiesSetting.jsx @@ -8,38 +8,30 @@ export default function PropertiesSetting(props) { const { handleSetEaves, handleSetGable, handleRollback, handleFix, closeModal } = usePropertiesSetting(id) return ( - -
    -
    -

    {getMessage('modal.canvas.setting.wallline.properties.setting')}

    - + +
    +
    +
    + +
    -
    -
    {getMessage('modal.canvas.setting.wallline.properties.setting.info')}
    -
    -
    {getMessage('setting')}
    -
    - - -
    -
    -
    - - -
    -
    -
    -
    + ) } diff --git a/src/components/floor-plan/modal/outerlinesetting/WallLineSetting.jsx b/src/components/floor-plan/modal/outerlinesetting/WallLineSetting.jsx index c95c7c5a..36d79cb6 100644 --- a/src/components/floor-plan/modal/outerlinesetting/WallLineSetting.jsx +++ b/src/components/floor-plan/modal/outerlinesetting/WallLineSetting.jsx @@ -114,22 +114,18 @@ export default function WallLineSetting(props) { } return ( - -
    -
    -

    {getMessage('modal.cover.outline.drawing')}

    - -
    -
    -
    - + */} - -
    -
    - {type === OUTER_LINE_TYPE.OUTER_LINE ? ( - - ) : type === OUTER_LINE_TYPE.RIGHT_ANGLE ? ( - - ) : type === OUTER_LINE_TYPE.DOUBLE_PITCH ? ( - - ) : type === OUTER_LINE_TYPE.ANGLE ? ( - - ) : type === OUTER_LINE_TYPE.DIAGONAL_LINE ? ( - - ) : ( - <> - )} -
    -
    - - -
    + */}
    -
    -
    +
    + {type === OUTER_LINE_TYPE.OUTER_LINE ? ( + + ) : type === OUTER_LINE_TYPE.RIGHT_ANGLE ? ( + + ) : type === OUTER_LINE_TYPE.DOUBLE_PITCH ? ( + + ) : type === OUTER_LINE_TYPE.ANGLE ? ( + + ) : type === OUTER_LINE_TYPE.DIAGONAL_LINE ? ( + + ) : ( + <> + )} +
    +
    + + +
    +
    ) } diff --git a/src/components/floor-plan/modal/panelBatch/PanelBatchStatistics.jsx b/src/components/floor-plan/modal/panelBatch/PanelBatchStatistics.jsx index 8cd0de0e..fa4703be 100644 --- a/src/components/floor-plan/modal/panelBatch/PanelBatchStatistics.jsx +++ b/src/components/floor-plan/modal/panelBatch/PanelBatchStatistics.jsx @@ -11,25 +11,31 @@ import { canvasState } from '@/store/canvasAtom' import { POLYGON_TYPE } from '@/common/common' import { useCircuitTrestle } from '@/hooks/useCirCuitTrestle' import { moduleSelectionDataState } from '@/store/selectedModuleOptions' +import Draggable from 'react-draggable' export default function PanelBatchStatistics() { const { getMessage } = useMessage() const [isFold, setIsFold] = useState(false) - const [pos, setPos] = useState({ + const canvas = useRecoilValue(canvasState) + const { header, rows, footer } = useRecoilValue(moduleStatisticsState) + const { setModuleStatisticsData } = useCircuitTrestle(true) + const [moduleSelectionDataStore, setModuleSelectionDataStore] = useRecoilState(moduleSelectionDataState) + const [position, setPosition] = useState({ x: 0, y: 30, }) - const canvas = useRecoilValue(canvasState) - const { header, rows, footer } = useRecoilValue(moduleStatisticsState) - const { setModuleStatisticsData } = useCircuitTrestle() - const [moduleSelectionDataStore, setModuleSelectionDataStore] = useRecoilState(moduleSelectionDataState) + + const handleOnDrag = (e, data) => { + e.stopPropagation() + setPosition({ x: data.x, y: data.y }) + } useEffect(() => { if (moduleSelectionDataStore && moduleSelectionDataStore.module) setModuleStatisticsData() }, []) return ( - + handleOnDrag(e, data)} handle=".penal-wrap">

    {getMessage('modal.panel.batch.statistic')}

    @@ -63,6 +69,6 @@ export default function PanelBatchStatistics() {
    名称昇圧回路数{getMessage('modal.circuit.trestle.setting.power.conditional.select.name')} {getMessage('modal.circuit.trestle.setting.step.up.allocation.circuit.amount')}
    {typeof row[header.prop] === 'number' - ? row[header.prop].toLocaleString('ko-KR', { maximumFractionDigits: 4 }) - : row[header.prop]} + ? (row[header.prop] ?? 0).toLocaleString('ko-KR', { maximumFractionDigits: 4 }) + : (row[header.prop] ?? 0)}
    -
    + ) } diff --git a/src/components/floor-plan/modal/placementShape/PlacementShapeDrawing.jsx b/src/components/floor-plan/modal/placementShape/PlacementShapeDrawing.jsx index 71bed775..04b63f1d 100644 --- a/src/components/floor-plan/modal/placementShape/PlacementShapeDrawing.jsx +++ b/src/components/floor-plan/modal/placementShape/PlacementShapeDrawing.jsx @@ -121,45 +121,33 @@ export default function PlacementShapeDrawing({ id, pos = { x: 50, y: 230 } }) { setType(button.type) } return ( - -
    -
    -

    {getMessage('plan.menu.placement.surface.drawing')}

    - + ))} +
    +
    + {buttonAct === 1 && } + {buttonAct === 2 && } + {buttonAct === 3 && } + {buttonAct === 4 && } + {buttonAct === 5 && } +
    + +
    + +
    -
    -
    - {types.map((type, idx) => ( - - ))} -
    -
    - {buttonAct === 1 && } - {buttonAct === 2 && } - {buttonAct === 3 && } - {buttonAct === 4 && } - {buttonAct === 5 && } -
    - -
    - - -
    -
    -
    -
    +
    ) } diff --git a/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx b/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx index 4fd70281..a70a8c65 100644 --- a/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx +++ b/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx @@ -9,30 +9,42 @@ import WithDraggable from '@/components/common/draggable/WithDraggable' import { useCanvasSetting } from '@/hooks/option/useCanvasSetting' import { useRecoilState, useRecoilValue } from 'recoil' -import { addedRoofsState, roofMaterialsAtom } from '@/store/settingAtom' +import { addedRoofsState, roofDisplaySelector, roofMaterialsAtom } from '@/store/settingAtom' import { useCommonCode } from '@/hooks/common/useCommonCode' import QSelectBox from '@/components/common/select/QSelectBox' import { globalLocaleStore } from '@/store/localeAtom' import { onlyNumberInputChange } from '@/util/input-utils' +import { getChonByDegree, getDegreeByChon } from '@/util/canvas-util' +import { usePolygon } from '@/hooks/usePolygon' +import { canvasState } from '@/store/canvasAtom' +import { useRoofFn } from '@/hooks/common/useRoofFn' +/** + * 지붕 레이아웃 + */ export const ROOF_MATERIAL_LAYOUT = { PARALLEL: 'P', STAIRS: 'S', } -export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, setShowPlaceShapeModal }) { + +export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, planNo, openPoint }) { const [showSizeGuideModal, setShowSizeGuidModal] = useState(false) const [showMaterialGuideModal, setShowMaterialGuidModal] = useState(false) - const { closePopup } = usePopup() const { getMessage } = useMessage() const roofMaterials = useRecoilValue(roofMaterialsAtom) const globalLocale = useRecoilValue(globalLocaleStore) - const { basicSetting, setBasicSettings, basicSettingSave } = useCanvasSetting() + const { basicSetting, setBasicSettings, fetchBasicSettings, basicSettingSave } = useCanvasSetting() const [addedRoofs, setAddedRoofs] = useRecoilState(addedRoofsState) const { findCommonCode } = useCommonCode() - const [raftCodes, setRaftCodes] = useState([]) // 서까래 정보 - const [currentRoof, setCurrentRoof] = useState(null) // 현재 선택된 지붕재 정보 + const [raftCodes, setRaftCodes] = useState([]) /** 서까래 정보 */ + const [currentRoof, setCurrentRoof] = useState(null) /** 현재 선택된 지붕재 정보 */ + const { closePopup } = usePopup() /** usePopup에서 closePopup 함수 가져오기 */ + const { drawDirectionArrow } = usePolygon() + const { setSurfaceShapePattern } = useRoofFn() + const canvas = useRecoilValue(canvasState) + const roofDisplay = useRecoilValue(roofDisplaySelector) const roofRef = { roofCd: useRef(null), @@ -42,72 +54,89 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set hajebichi: useRef(null), } - //치수 입력방법(복시도입력/실측값입력/육지붕) + /** + * 치수 입력방법(복시도입력/실측값입력/육지붕) + */ const roofSizeSetArray = [ { id: 'ra01', name: 'roofSizeSet', value: '1', message: 'modal.placement.initial.setting.size.roof' }, { id: 'ra02', name: 'roofSizeSet', value: '2', message: 'modal.placement.initial.setting.size.actual' }, { id: 'ra03', name: 'roofSizeSet', value: '3', message: 'modal.placement.initial.setting.size.none.pitch' }, ] - //지붕각도 설정(경사/각도) + /** + * 지붕각도 설정(경사/각도) + */ const roofAngleSetArray = [ { id: 'ra04', name: 'roofAngleSet', value: 'slope', message: 'modal.placement.initial.setting.roof.pitch' }, { id: 'ra05', name: 'roofAngleSet', value: 'flat', message: 'modal.placement.initial.setting.roof.angle' }, ] - const defaultRoofSettings = { - roofSizeSet: '1', // 기본 치수 입력 방법 - roofAngleSet: 'slope', // 기본 지붕 각도 설정 + /** + * 지붕재 초기값 + */ + const DEFAULT_ROOF_SETTINGS = { + roofSizeSet: '1', + roofAngleSet: 'slope', angle: 21.8, - hajebichi: '', + hajebichi: null, id: 'ROOF_ID_WA_53A', index: 0, layout: ROOF_MATERIAL_LAYOUT.PARALLEL, lenAuth: 'R', lenBase: '235.000', - length: '235', + length: 235, name: '일본기와 A', nameJp: '和瓦A', pitch: 4, + planNo: planNo, raft: '', raftAuth: 'C', raftBaseCd: 'HEI_455', - roofAngleSet: 'slope', roofCd: '', roofMatlCd: 'ROOF_ID_WA_53A', roofMatlNm: '일본기와 A', roofMatlNmJp: '和瓦A', roofPchAuth: null, roofPchBase: null, - roofSizeSet: '1', selected: true, widAuth: 'R', widBase: '265.000', - width: '265', + width: 265, } + useEffect(() => { + /** + * 메뉴에서 배치면초기설정 선택 시 조회 후 화면 오픈 + */ + if (openPoint && openPoint === 'canvasMenus') fetchBasicSettings(planNo, openPoint) + }, []) + + /** + * 배치면초기설정 데이터 조회 후 화면 오픈 + */ useEffect(() => { if (addedRoofs.length > 0) { const raftCodeList = findCommonCode('203800') setRaftCodes(raftCodeList) - - // 데이터 설정 확인 후 데이터가 없으면 기본 데이터 설정 - if (addedRoofs.length > 0) { - setCurrentRoof({ ...addedRoofs[0] }) - } else { - setCurrentRoof(defaultRoofSettings) - } + setCurrentRoof({ ...addedRoofs[0], planNo: planNo, roofSizeSet: String(basicSetting.roofSizeSet), roofAngleSet: basicSetting.roofAngleSet }) + } else { + /** 데이터 설정 확인 후 데이터가 없으면 기본 데이터 설정 */ + setCurrentRoof({ ...DEFAULT_ROOF_SETTINGS }) } }, [addedRoofs]) + /** + * 배치면초기설정 정보 변경 시 basicSettings 설정 + */ useEffect(() => { - //console.log('🚀 ~ fetchBasicSettings ~ currentRoof :', currentRoof) if (!currentRoof) return setBasicSettings({ ...basicSetting, + planNo: Number(currentRoof.planNo), roofSizeSet: String(currentRoof.roofSizeSet), roofAngleSet: currentRoof.roofAngleSet, roofsData: { + planNo: Number(currentRoof.planNo), roofApply: true, roofSeq: 0, roofMatlCd: currentRoof.roofMatlCd, @@ -130,28 +159,56 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set setCurrentRoof({ ...currentRoof, roofAngleSet: value }) } - // Function to update the roofType and corresponding values + /** + * 지붕재 변경 시 현재 지붕 정보 변경 + */ const handleRoofTypeChange = (value) => { const selectedRoofMaterial = roofMaterials.find((roof) => roof.roofMatlCd === value) - setCurrentRoof({ ...selectedRoofMaterial, index: 0, roofSizeSet: String(currentRoof.roofSizeSet), roofAngleSet: currentRoof.roofAngleSet }) + + setCurrentRoof({ + ...selectedRoofMaterial, + pitch: currentRoof?.pitch, + angle: currentRoof?.angle, + index: 0, + planNo: currentRoof.planNo, + roofSizeSet: String(currentRoof.roofSizeSet), + roofAngleSet: currentRoof.roofAngleSet, + }) } + /** + * 입력 값 변경 시 현재 지붕 정보 변경 + */ const changeInput = (value, e) => { const { name } = e.target setCurrentRoof({ ...currentRoof, [name]: Number(value) }) } + /** + * 서까래 변경 시 현재 지붕 정보 변경 + */ const handleRafterChange = (value) => { setCurrentRoof({ ...currentRoof, raft: value }) } + /** + * 지붕 레이아웃 변경 시 현재 지붕 정보 변경 + */ const handleRoofLayoutChange = (value) => { + if (+currentRoof.roofSizeSet === 3) { + setCurrentRoof({ ...currentRoof, layout: ROOF_MATERIAL_LAYOUT.PARALLEL }) + return + } setCurrentRoof({ ...currentRoof, layout: value }) } + /** + * 배치면초기설정 저장 버튼 클릭 + */ const handleSaveBtn = () => { const roofInfo = { ...currentRoof, + planNo: basicSetting.planNo, roofCd: roofRef.roofCd.current?.value, width: roofRef.width.current?.value, length: roofRef.length.current?.value, @@ -169,268 +226,236 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set console.log('save Info', { ...basicSetting, selectedRoofMaterial: { - // 선택된 지붕재 정보 roofInfo, }, }) - // 배치면초기설정 저장 + /** + * 배치면초기설정 저장 + */ basicSettingSave({ ...basicSetting, + /** + * 선택된 지붕재 정보 + */ selectedRoofMaterial: { - // 선택된 지붕재 정보 roofInfo, }, }) + + const roofs = canvas.getObjects().filter((obj) => obj.roofMaterial?.index === 0) + + roofs.forEach((roof) => { + /** 모양 패턴 설정 */ + setSurfaceShapePattern(roof, roofDisplay.column, false, { ...roofInfo }) + roof.roofMaterial = { ...roofInfo } + drawDirectionArrow(roof) + }) + + /* 저장 후 화면 닫기 */ + closePopup(id) } return ( - -
    -
    -

    {getMessage('plan.menu.placement.surface.initial.setting')}

    - -
    -
    -
    - - - - - - - - - - - - - - - - - + + +
    {getMessage('modal.placement.initial.setting.plan.drawing')}{getMessage('modal.placement.initial.setting.plan.drawing.size.stuff')}
    -
    - {getMessage('modal.placement.initial.setting.size')} - -
    -
    -
    - {currentRoof && - roofSizeSetArray.map((item) => ( -
    - setCurrentRoof({ ...currentRoof, roofSizeSet: e.target.value })} - /> - -
    - ))} -
    -
    {getMessage('modal.placement.initial.setting.roof.angle.setting')} -
    - {currentRoof && - roofAngleSetArray.map((item, index) => ( -
    - -
    - setCurrentRoof({ ...currentRoof, roofAngleSet: e.target.value })} - /> - -
    -
    -
    + + + +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + - - - - - - -
    {getMessage('modal.placement.initial.setting.plan.drawing')}{getMessage('modal.placement.initial.setting.plan.drawing.size.stuff')}
    +
    + {getMessage('modal.placement.initial.setting.size')} + +
    +
    +
    + {currentRoof && + roofSizeSetArray.map((item) => ( +
    + setCurrentRoof({ ...currentRoof, roofSizeSet: e.target.value })} + /> + +
    + ))} +
    +
    {getMessage('modal.placement.initial.setting.roof.angle.setting')} +
    + {currentRoof && + roofAngleSetArray.map((item, index) => ( +
    + +
    - index === 0 - ? setCurrentRoof({ ...currentRoof, pitch: e.target.value }) - : setCurrentRoof({ ...currentRoof, angle: e.target.value }) - } + type="radio" + id={item.id} + name={item.name} + value={item.value} + checked={String(currentRoof?.roofAngleSet) === item.value} + onChange={(e) => setCurrentRoof({ ...currentRoof, roofAngleSet: e.target.value })} /> +
    - {index === 0 ? '寸' : '度'} +
    +
    + + index === 0 + ? setCurrentRoof({ ...currentRoof, pitch: e.target.value, angle: getDegreeByChon(e.target.value) }) + : setCurrentRoof({ ...currentRoof, pitch: getChonByDegree(e.target.value), angle: e.target.value }) + } + />
    - ))} + {index === 0 ? '寸' : '度'} +
    + ))} +
    +
    +
    + {getMessage('modal.placement.initial.setting.roof.material')} + +
    +
    +
    +
    + { + return { ...roof, name: globalLocale === 'ko' ? roof.roofMatlNm : roof.roofMatlNmJp } + })} + value={currentRoof?.roofSizeSet === '3' ? null : currentRoof?.roofMatlCd} + onChange={(e) => handleRoofTypeChange(e.roofMatlCd)} + sourceKey="id" + targetKey="id" + showKey="name" + disabled={currentRoof?.roofSizeSet === '3'} + />
    -
    -
    - {getMessage('modal.placement.initial.setting.roof.material')} - -
    -
    -
    -
    - { - return { ...roof, name: globalLocale === 'ko' ? roof.roofMatlNm : roof.roofMatlNmJp } - })} - value={currentRoof?.roofSizeSet === '3' ? null : currentRoof?.roofMatlCd} - onChange={(e) => handleRoofTypeChange(e.roofMatlCd)} - sourceKey="id" - targetKey="id" - showKey="name" - disabled={currentRoof?.roofSizeSet === '3'} - /> - {/* */} + {currentRoof && ['R', 'C'].includes(currentRoof.widAuth) && ( +
    + W +
    + onlyNumberInputChange(e, changeInput)} + readOnly={currentRoof?.widAuth === 'R'} + disabled={currentRoof?.roofSizeSet === '3'} + /> +
    - {currentRoof && ['R', 'C'].includes(currentRoof.widAuth) && ( -
    - W -
    - onlyNumberInputChange(e, changeInput)} - readOnly={currentRoof?.widAuth === 'R'} + )} + {currentRoof && ['R', 'C'].includes(currentRoof.lenAuth) && ( +
    + L +
    + onlyNumberInputChange(e, changeInput)} + readOnly={currentRoof?.lenAuth === 'R'} + disabled={currentRoof?.roofSizeSet === '3'} + /> +
    +
    + )} + {currentRoof && ['C', 'R'].includes(currentRoof.raftAuth) && ( +
    + {getMessage('modal.placement.initial.setting.rafter')} + {raftCodes?.length > 0 && ( +
    + r.clCode === (currentRoof?.raft === undefined ? currentRoof?.raftBaseCd : currentRoof?.raft)) + .clCodeNm + } + value={currentRoof?.raft === undefined ? currentRoof?.raftBaseCd : currentRoof?.raft} + onChange={(e) => handleRafterChange(e.clCode)} + sourceKey="clCode" + targetKey={currentRoof?.raft ? 'raft' : 'raftBaseCd'} + showKey="clCodeNm" disabled={currentRoof?.roofSizeSet === '3'} />
    - {/*
    - -
    */} + )} +
    + )} + {currentRoof && ['C', 'R'].includes(currentRoof?.roofPchAuth) && ( +
    + {getMessage('hajebichi')} +
    + onlyNumberInputChange(e, changeInput)} + readOnly={currentRoof?.roofPchAuth === 'R'} + disabled={currentRoof?.roofSizeSet === '3'} + />
    - )} - {currentRoof && ['R', 'C'].includes(currentRoof.lenAuth) && ( -
    - L -
    - onlyNumberInputChange(e, changeInput)} - readOnly={currentRoof?.lenAuth === 'R'} - disabled={currentRoof?.roofSizeSet === '3'} - /> -
    - {/*
    - -
    */} -
    - )} - {currentRoof && ['C', 'R'].includes(currentRoof.raftAuth) && ( -
    - {getMessage('modal.placement.initial.setting.rafter')} - {raftCodes?.length > 0 && ( -
    - r.clCode === (currentRoof?.raft === undefined ? currentRoof?.raftBaseCd : currentRoof?.raft)) - .clCodeNm - } - value={currentRoof?.raft === undefined ? currentRoof?.raftBaseCd : currentRoof?.raft} - onChange={(e) => handleRafterChange(e.clCode)} - sourceKey="clCode" - targetKey={currentRoof?.raft ? 'raft' : 'raftBaseCd'} - showKey="clCodeNm" - disabled={currentRoof?.roofSizeSet === '3'} - /> - {/* */} -
    - )} -
    - )} - {currentRoof && ['C', 'R'].includes(currentRoof?.roofPchAuth) && ( -
    - {getMessage('hajebichi')} -
    - onlyNumberInputChange(e, changeInput)} - readOnly={currentRoof?.roofPchAuth === 'R'} - disabled={currentRoof?.roofSizeSet === '3'} - /> -
    -
    - )} -
    - {currentRoof && ( +
    + )} +
    + {/* {currentRoof && (
    - )} -
    -
    -
    - -
    + )} */} +
    - {showSizeGuideModal && } - {showMaterialGuideModal && } -
    -
    +
    + +
    + + {showSizeGuideModal && } + {showMaterialGuideModal && } ) } diff --git a/src/components/floor-plan/modal/placementShape/PlacementSurfaceLineProperty.jsx b/src/components/floor-plan/modal/placementShape/PlacementSurfaceLineProperty.jsx new file mode 100644 index 00000000..34cf8c1e --- /dev/null +++ b/src/components/floor-plan/modal/placementShape/PlacementSurfaceLineProperty.jsx @@ -0,0 +1,73 @@ +import WithDraggable from '@/components/common/draggable/WithDraggable' +import { useMessage } from '@/hooks/useMessage' +import { usePopup } from '@/hooks/usePopup' +import { useRoofLinePropertySetting } from '@/hooks/surface/useRoofLinePropertySetting' +import { useEffect } from 'react' +import { LINE_TYPE } from '@/common/common' +import { useSwal } from '@/hooks/useSwal' + +export default function PlacementSurfaceLineProperty(props) { + const { id, pos = { x: 50, y: 230 }, roof, setIsHidden } = props + const { closePopup } = usePopup() + // const { handleSetEaves, handleSetGable, handleRollback, handleFix, closeModal } = usePropertiesSetting(id) + const { roofLinesInit, handleSetRidge, handleSetEaves, handleSetGable, handleRollback, handleFix, handleClosed } = useRoofLinePropertySetting({ + id, + roof, + setIsHidden, + }) + const { getMessage } = useMessage() + const { swalFire } = useSwal() + + useEffect(() => { + roofLinesInit(roof) + }, []) + + const handleClose = () => { + const notSettingLines = roof.lines.filter( + (line) => + !line.attributes.type || ![LINE_TYPE.WALLLINE.EAVES, LINE_TYPE.WALLLINE.GABLE, LINE_TYPE.SUBLINE.RIDGE].includes(line.attributes.type), + ) + if (notSettingLines.length > 0) { + swalFire({ text: getMessage('modal.canvas.setting.roofline.properties.setting.not.setting'), type: 'alert', icon: 'warning' }) + return + } + + closePopup(id) + handleClosed() + + if (setIsHidden) { + setIsHidden(false) + } + } + + return ( + + handleClose()} /> + +
    {getMessage('modal.canvas.setting.roofline.properties.setting.info')}
    +
    +
    {getMessage('setting')}
    +
    + + + +
    +
    +
    + + +
    +
    +
    + ) +} diff --git a/src/components/floor-plan/modal/placementSurface/PlacementSurface.jsx b/src/components/floor-plan/modal/placementSurface/PlacementSurface.jsx index f95f9c2f..7ab89106 100644 --- a/src/components/floor-plan/modal/placementSurface/PlacementSurface.jsx +++ b/src/components/floor-plan/modal/placementSurface/PlacementSurface.jsx @@ -11,23 +11,42 @@ const PlacementSurface = forwardRef((props, refs) => { const num = ['①', '②', '③', '④', '⑤'] const getImageUrl = () => { + // re_는 normal의 y축 대칭 이미지 + const imageName = id < 10 ? '0' + id : id + let imageRotate = 0 if (xInversion && !yInversion) { - return `/static/images/canvas/shape/re_${(rotate - 2) % 4 !== 0 ? Math.abs((rotate - 2) % 4) * 90 + 'deg' : 'normal'}/plane_tab${id < 10 ? '0' + id : id}.svg` + if (rotate % 2 === 0 || rotate < 0) { + imageRotate = Math.abs(rotate % 4) + } else { + if (rotate < 0) { + imageRotate = Math.abs((rotate - 2) % 4) + } else { + imageRotate = Math.abs((rotate + 2) % 4) + } + } + } else if (xInversion && yInversion) { + imageRotate = Math.abs((rotate + 4) % 4) + } else if (xInversion !== yInversion && rotate < 0) { + imageRotate = Math.abs(rotate) + } else if (!xInversion && yInversion) { + if (rotate % 2 === 0 || rotate < 0) { + imageRotate = Math.abs(rotate % 4) + } else { + if (rotate < 0) { + imageRotate = Math.abs((rotate - 2) % 4) + } else { + imageRotate = Math.abs((rotate + 2) % 4) + } + } + } else { + imageRotate = (rotate + 4) % 4 } - - if (!xInversion && yInversion) { - return `/static/images/canvas/shape/re_${rotate % 4 !== 0 ? Math.abs(rotate % 4) * 90 + 'deg' : 'normal'}/plane_tab${id < 10 ? '0' + id : id}.svg` + const rotateType = imageRotate % 4 !== 0 ? (imageRotate % 4) * 90 + 'deg' : 'normal' + if (xInversion !== yInversion) { + return `/static/images/canvas/shape/re_${rotateType}/plane_tab${imageName}.svg` + } else { + return `/static/images/canvas/shape/${rotateType}/plane_tab${imageName}.svg` } - - if (xInversion && yInversion) { - return `/static/images/canvas/shape/${(rotate + 2) % 4 !== 0 ? Math.abs((rotate + 2) % 4) * 90 + 'deg' : 'normal'}/plane_tab${id < 10 ? '0' + id : id}.svg` - } - - if (rotate < 0) { - return `/static/images/canvas/shape/${rotate !== 0 ? Math.abs((rotate + 4) * 90) + 'deg' : 'normal'}/plane_tab${id < 10 ? '0' + id : id}.svg` - } - - return `/static/images/canvas/shape/${rotate !== 0 ? Math.abs(rotate * 90) + 'deg' : 'normal'}/plane_tab${id < 10 ? '0' + id : id}.svg` } const azimuthButton = (direction, e) => { diff --git a/src/components/floor-plan/modal/placementSurface/PlacementSurfaceSetting.jsx b/src/components/floor-plan/modal/placementSurface/PlacementSurfaceSetting.jsx index 263054cf..ae29b778 100644 --- a/src/components/floor-plan/modal/placementSurface/PlacementSurfaceSetting.jsx +++ b/src/components/floor-plan/modal/placementSurface/PlacementSurfaceSetting.jsx @@ -224,7 +224,7 @@ export default function PlacementSurfaceSetting({ id, pos = { x: 50, y: 230 } }) } const getScale = () => { - return `scale(${yInversion ? -1 : 1}, ${xInversion ? -1 : 1})` + return `scale(${xInversion !== yInversion ? -1 : 1}, 1)` } const getRotate = () => { @@ -239,63 +239,66 @@ export default function PlacementSurfaceSetting({ id, pos = { x: 50, y: 230 } }) applySurfaceShape(surfaceRefs, selectedType, id) } + const handleInversion = (type) => { + if (type === 'x') { + const x = xInversion + setXInversion(!xInversion) + setRotate(x ? rotate + 2 : rotate - 2) + // setXInversion(!xInversion) + } else if (type === 'y') { + // setRotate(rotate + 2) + setYInversion(!yInversion) + } + } + useEffect(() => { setSelectedType(types[0]) }, []) return ( - -
    -
    -

    {getMessage('plan.menu.placement.surface.arrangement')}

    - -
    -
    -
    -
    -
    - {types.map((type) => ( - - ))} -
    -
    - - - -
    -
    -
    - -
    - -
    + ))} +
    +
    + + {/* */} + {/* + */} + + +
    +
    +
    + +
    +
    -
    -
    +
    ) } diff --git a/src/components/floor-plan/modal/roofAllocation/ActualSizeSetting.jsx b/src/components/floor-plan/modal/roofAllocation/ActualSizeSetting.jsx index d9456bbd..c91325c0 100644 --- a/src/components/floor-plan/modal/roofAllocation/ActualSizeSetting.jsx +++ b/src/components/floor-plan/modal/roofAllocation/ActualSizeSetting.jsx @@ -61,63 +61,50 @@ export default function ActualSizeSetting(props) { } return ( - -
    -
    -

    {getMessage('modal.actual.size.setting')}

    - + + closePopup(id)} /> + +
    + {getMessage('modal.actual.size.setting.info')}
    -
    -
    - {getMessage('modal.actual.size.setting.info')} -
    -
    -
    {getMessage('setting')}
    -
    -
    -
    -
    {getMessage('modal.actual.size.setting.plane.size.length')}
    -
    -
    -
    - -
    - mm +
    +
    {getMessage('setting')}
    +
    +
    +
    +
    {getMessage('modal.actual.size.setting.plane.size.length')}
    +
    +
    +
    +
    + mm
    -
    -
    {getMessage('modal.actual.size.setting.actual.size.length')}
    -
    -
    -
    - setActualSize(Number(e.target.value))} - /> -
    - mm +
    +
    +
    {getMessage('modal.actual.size.setting.actual.size.length')}
    +
    +
    +
    + setActualSize(Number(e.target.value))} />
    + mm
    -
    - - -
    -
    -
    +
    + + +
    + ) } diff --git a/src/components/floor-plan/modal/roofAllocation/ContextRoofAllocationSetting.jsx b/src/components/floor-plan/modal/roofAllocation/ContextRoofAllocationSetting.jsx index a4cfa8dd..dd8b7003 100644 --- a/src/components/floor-plan/modal/roofAllocation/ContextRoofAllocationSetting.jsx +++ b/src/components/floor-plan/modal/roofAllocation/ContextRoofAllocationSetting.jsx @@ -23,6 +23,7 @@ export default function ContextRoofAllocationSetting(props) { onAddRoofMaterial, onDeleteRoofMaterial, roofMaterials, + currentRoofMaterial, setCurrentRoofMaterial, roofList, handleDefaultRoofMaterial, @@ -46,26 +47,19 @@ export default function ContextRoofAllocationSetting(props) { }, []) return ( - -
    - {currentRoofList && ( - <> -
    -

    {getMessage('plan.menu.estimate.roof.alloc')}

    - -
    -
    -
    {getMessage('modal.roof.alloc.info')}
    -
    - {getMessage('modal.roof.alloc.select.roof.material')} + + closePopup(id)} /> + {currentRoofList && ( + +
    {getMessage('modal.roof.alloc.info')}
    +
    + {/* {getMessage('modal.roof.alloc.select.roof.material')}
    { return { ...roof, name: globalLocale === 'ko' ? roof.roofMatlNm : roof.roofMatlNmJp } })} - value={roofMaterials[0]} + value={currentRoofMaterial} onChange={(e) => { // const selected = roofMaterials.find((roofMaterial) => roofMaterial.roofMatlCd === e.id) setCurrentRoofMaterial(e) @@ -74,186 +68,163 @@ export default function ContextRoofAllocationSetting(props) { sourceKey={'roofMatlCd'} targetKey={'roofMatlCd'} /> -
    - -
    -
    -
    - {currentRoofList.map((roof, index) => { - return ( -
    -
    - - +
    */} + +
    +
    +
    + {currentRoofList.map((roof, index) => { + return ( +
    +
    + + +
    +
    +
    +
    +
    + { + return { ...roof2, name: globalLocale === 'ko' ? roof2.roofMatlNm : roof2.roofMatlNmJp } + })} + value={roof} + //showKey={'roofMatlNm'} + showKey="name" + sourceKey={'roofMatlCd'} + targetKey={'roofMatlCd'} + onChange={(e) => handleChangeRoofMaterial(e, index)} + /> +
    + {index === 0 && {getMessage('modal.roof.alloc.default.roof.material')}} + {index !== 0 && ( + + + + )}
    -
    -
    -
    +
    + {roof.raftAuth && ( +
    +
    + {getMessage('modal.placement.initial.setting.rafter')} + {raftCodes.length > 0 && (
    { - return { ...roof2, name: globalLocale === 'ko' ? roof2.roofMatlNm : roof2.roofMatlNmJp } - })} + options={raftCodes} value={roof} - //showKey={'roofMatlNm'} - showKey="name" - sourceKey={'roofMatlCd'} - targetKey={'roofMatlCd'} - onChange={(e) => handleChangeRoofMaterial(e, index)} + showKey={'clCodeNm'} + sourceKey={'clCode'} + targetKey={roof.raft ? 'raft' : 'raftBaseCd'} + onChange={(e) => handleChangeRaft(e, index)} />
    - {index === 0 && {getMessage('modal.roof.alloc.default.roof.material')}} - {index !== 0 && ( - - - - )} -
    + )}
    - {roof.raftAuth && ( -
    -
    - {getMessage('modal.placement.initial.setting.rafter')} - {raftCodes.length > 0 && ( -
    - -
    - )} -
    -
    - )} +
    + )} - {(roof.widAuth || roof.lenAuth) && ( - <> - {roof.widAuth && ( -
    -
    - W -
    - { - handleChangeInput(e, 'width', index) - }} - /> -
    -
    -
    - )} - {roof.lenAuth && ( -
    -
    - L -
    - { - handleChangeInput(e, 'length', index) - }} - /> -
    -
    -
    - )} - - )} - {roof.roofPchAuth && ( + {(roof.widAuth || roof.lenAuth) && ( + <> + {roof.widAuth && (
    - {getMessage('hajebichi')} + W
    handleChangeInput(e, 'hajebichi', index)} + defaultValue={roof.width} + readOnly={roof.widAuth === 'R'} + onChange={(e) => { + handleChangeInput(e, 'width', index) + }} />
    )} -
    -
    - {getMessage('slope')} -
    - { - // handleChangeInput(e, currentAngleType === 'slope' ? 'pitch' : 'angle', index) - handleChangePitch(e, index) - }} - value={currentAngleType === 'slope' ? roof.pitch : roof.angle} - defaultValue={currentAngleType === 'slope' ? roof.pitch : roof.angle} - /> + {roof.lenAuth && ( +
    +
    + L +
    + { + handleChangeInput(e, 'length', index) + }} + /> +
    - {pitchText}
    -
    -
    -
    - - + )} + + )} + {roof.roofPchAuth && ( +
    +
    + {getMessage('hajebichi')} +
    + handleChangeInput(e, 'hajebichi', index)} + />
    + )} +
    +
    + {getMessage('modal.object.setting.offset.slope')} +
    + { + // handleChangeInput(e, currentAngleType === 'slope' ? 'pitch' : 'angle', index) + handleChangePitch(e, index) + }} + value={currentAngleType === 'slope' ? roof.pitch : roof.angle} + defaultValue={currentAngleType === 'slope' ? roof.pitch : roof.angle} + /> +
    + {pitchText} +
    - ) - })} -
    -
    -
    - -
    +
    +
    + ) + })}
    - - )} -
    -
    +
    +
    + +
    + + )} ) } diff --git a/src/components/floor-plan/modal/roofAllocation/RoofAllocationSetting.jsx b/src/components/floor-plan/modal/roofAllocation/RoofAllocationSetting.jsx index 9ceeb9e0..0603ed96 100644 --- a/src/components/floor-plan/modal/roofAllocation/RoofAllocationSetting.jsx +++ b/src/components/floor-plan/modal/roofAllocation/RoofAllocationSetting.jsx @@ -25,6 +25,7 @@ export default function RoofAllocationSetting(props) { onAddRoofMaterial, onDeleteRoofMaterial, roofMaterials, + currentRoofMaterial, setCurrentRoofMaterial, roofList, handleDefaultRoofMaterial, @@ -46,26 +47,20 @@ export default function RoofAllocationSetting(props) { }, []) return ( - -
    + + closePopup(id)} /> + {currentRoofList && ( <> -
    -

    {getMessage('plan.menu.estimate.roof.alloc')}

    - -
    -
    -
    {getMessage('modal.roof.alloc.info')}
    -
    - {getMessage('modal.roof.alloc.select.roof.material')} +
    {getMessage('modal.roof.alloc.info')}
    +
    + {/* {getMessage('modal.roof.alloc.select.roof.material')}
    { return { ...roof, name: globalLocale === 'ko' ? roof.roofMatlNm : roof.roofMatlNmJp } })} - value={roofMaterials[0]} + value={currentRoofMaterial} onChange={(e) => { // const selected = roofMaterials.find((roofMaterial) => roofMaterial.roofMatlCd === e.id) setCurrentRoofMaterial(e) @@ -74,147 +69,147 @@ export default function RoofAllocationSetting(props) { sourceKey={'roofMatlCd'} targetKey={'roofMatlCd'} /> -
    - -
    -
    -
    - {currentRoofList.map((roof, index) => { - return ( -
    -
    - - +
    */} + +
    +
    +
    + {currentRoofList.map((roof, index) => { + return ( +
    +
    + + +
    +
    +
    +
    +
    + { + return { ...roof2, name: globalLocale === 'ko' ? roof2.roofMatlNm : roof2.roofMatlNmJp } + })} + value={roof} + //showKey={'roofMatlNm'} + showKey="name" + sourceKey={'roofMatlCd'} + targetKey={'roofMatlCd'} + onChange={(e) => handleChangeRoofMaterial(e, index)} + /> +
    + {index === 0 && {getMessage('modal.roof.alloc.default.roof.material')}} + {index !== 0 && ( + + + + )} +
    -
    + + {roof.raftAuth && (
    -
    - { - return { ...roof2, name: globalLocale === 'ko' ? roof2.roofMatlNm : roof2.roofMatlNmJp } - })} - value={roof} - //showKey={'roofMatlNm'} - showKey="name" - sourceKey={'roofMatlCd'} - targetKey={'roofMatlCd'} - onChange={(e) => handleChangeRoofMaterial(e, index)} - /> -
    - {index === 0 && {getMessage('modal.roof.alloc.default.roof.material')}} - {index !== 0 && ( - - - + {getMessage('modal.placement.initial.setting.rafter')} + {raftCodes.length > 0 && ( +
    + handleChangeRaft(e, index)} + /> +
    )}
    + )} - {roof.raftAuth && ( -
    -
    - {getMessage('modal.placement.initial.setting.rafter')} - {raftCodes.length > 0 && ( -
    - handleChangeRaft(e, index)} + {(roof.widAuth || roof.lenAuth) && ( + <> + {roof.widAuth && ( +
    +
    + W +
    + handleChangeInput(e, 'width', index)} + readOnly={roof.widAuth === 'R'} />
    - )} -
    -
    - )} - - {(roof.widAuth || roof.lenAuth) && ( - <> - {roof.widAuth && ( -
    -
    - W -
    - handleChangeInput(e, 'width', index)} - readOnly={roof.widAuth === 'R'} - /> -
    -
    -
    - )} - {roof.lenAuth && ( -
    -
    - L -
    - handleChangeInput(e, 'length', index)} - readOnly={roof.lenAuth === 'R'} - /> -
    -
    -
    - )} - - )} - {roof.roofPchAuth && ( -
    -
    - {getMessage('hajebichi')} -
    - handleChangeInput(e, 'hajebichi', index)} - value={parseInt(roof.hajebichi)} - readOnly={roof.roofPchAuth === 'R'} - />
    -
    - )} + )} + {roof.lenAuth && ( +
    +
    + L +
    + handleChangeInput(e, 'length', index)} + readOnly={roof.lenAuth === 'R'} + /> +
    +
    +
    + )} + + )} + {roof.roofPchAuth && (
    - {getMessage('slope')} + {getMessage('hajebichi')}
    { - handleChangePitch(e, index) - }} - value={currentAngleType === 'slope' ? roof.pitch : roof.angle} - defaultValue={currentAngleType === 'slope' ? roof.pitch : roof.angle} + onChange={(e) => handleChangeInput(e, 'hajebichi', index)} + value={parseInt(roof.hajebichi)} + readOnly={roof.roofPchAuth === 'R'} />
    - {pitchText}
    -
    + )} +
    +
    + {getMessage('modal.object.setting.offset.slope')} +
    + { + handleChangePitch(e, index) + }} + value={currentAngleType === 'slope' ? roof.pitch : roof.angle} + defaultValue={currentAngleType === 'slope' ? roof.pitch : roof.angle} + /> +
    + {pitchText} +
    +
    + {/*
    -
    -
    +
    */}
    - ) - })} -
    -
    -
    - +
    + ) + })}
    +
    + +
    )} -
    -
    + ) } diff --git a/src/components/floor-plan/modal/roofShape/RoofShapePassivitySetting.jsx b/src/components/floor-plan/modal/roofShape/RoofShapePassivitySetting.jsx index b47d2356..7530bcdd 100644 --- a/src/components/floor-plan/modal/roofShape/RoofShapePassivitySetting.jsx +++ b/src/components/floor-plan/modal/roofShape/RoofShapePassivitySetting.jsx @@ -29,46 +29,38 @@ export default function RoofShapePassivitySetting({ id, pos = { x: 50, y: 230 } } return ( - -
    -
    -

    {getMessage('plan.menu.roof.cover.roof.shape.passivity.setting')}

    - + + closePopup(id)} /> + +
    + {buttons.map((button) => ( + + ))}
    -
    -
    - {buttons.map((button) => ( - - ))} -
    -
    -
    {getMessage('setting')}
    -
    - {type === TYPES.EAVES && } - {type === TYPES.GABLE && } - {type === TYPES.SHED && } -
    -
    - - -
    +
    +
    {getMessage('setting')}
    +
    + {type === TYPES.EAVES && } + {type === TYPES.GABLE && } + {type === TYPES.SHED && }
    - +
    -
    -
    +
    + +
    + ) } diff --git a/src/components/floor-plan/modal/roofShape/RoofShapeSetting.jsx b/src/components/floor-plan/modal/roofShape/RoofShapeSetting.jsx index 2a59cc91..73ccc348 100644 --- a/src/components/floor-plan/modal/roofShape/RoofShapeSetting.jsx +++ b/src/components/floor-plan/modal/roofShape/RoofShapeSetting.jsx @@ -88,39 +88,31 @@ export default function RoofShapeSetting({ id, pos = { x: 50, y: 230 } }) { } return ( - -
    -
    -

    {getMessage('modal.roof.shape.setting')}

    - + ))} +
    +
    + {shapeNum === 1 && } + {(shapeNum === 2 || shapeNum === 3) && } + {shapeNum === 4 && } + {(shapeNum === 5 || shapeNum === 6 || shapeNum === 7 || shapeNum === 8) && } +
    +
    +
    -
    -
    - {shapeMenu.map((item) => ( - - ))} -
    -
    - {shapeNum === 1 && } - {(shapeNum === 2 || shapeNum === 3) && } - {shapeNum === 4 && } - {(shapeNum === 5 || shapeNum === 6 || shapeNum === 7 || shapeNum === 8) && } -
    -
    - -
    -
    -
    -
    +
    ) } diff --git a/src/components/floor-plan/modal/roofShape/passivity/Eaves.jsx b/src/components/floor-plan/modal/roofShape/passivity/Eaves.jsx index 2ba0f3e3..c49cb3fa 100644 --- a/src/components/floor-plan/modal/roofShape/passivity/Eaves.jsx +++ b/src/components/floor-plan/modal/roofShape/passivity/Eaves.jsx @@ -1,10 +1,14 @@ import { useMessage } from '@/hooks/useMessage' import { useRecoilValue } from 'recoil' import { ANGLE_TYPE, currentAngleTypeSelector } from '@/store/canvasAtom' +import { selectedRoofMaterialSelector } from '@/store/settingAtom' +import { useEffect } from 'react' export default function Eaves({ offsetRef, pitchRef, pitchText }) { const { getMessage } = useMessage() const currentAngleType = useRecoilValue(currentAngleTypeSelector) + const selectedRoofMaterial = useRecoilValue(selectedRoofMaterialSelector) + return ( <>
    @@ -12,7 +16,12 @@ export default function Eaves({ offsetRef, pitchRef, pitchText }) { {getMessage('slope')}
    - +
    {pitchText}
    diff --git a/src/components/floor-plan/modal/setting01/SettingModal01.jsx b/src/components/floor-plan/modal/setting01/SettingModal01.jsx index 0ccd337a..4e6f91ea 100644 --- a/src/components/floor-plan/modal/setting01/SettingModal01.jsx +++ b/src/components/floor-plan/modal/setting01/SettingModal01.jsx @@ -72,37 +72,27 @@ export default function SettingModal01(props) { } return ( - <> - -
    -
    -

    {getMessage('modal.canvas.setting')}

    - -
    -
    -
    - + + closePopup(id, true)} /> + +
    + - - {canGridOptionSeletorValue && ( - - )} -
    - {buttonAct === 1 && } - {buttonAct === 2 && } - {buttonAct === 3 && } -
    -
    + + {canGridOptionSeletorValue && ( + + )}
    - - + {buttonAct === 1 && } + {buttonAct === 2 && } + {buttonAct === 3 && } + + ) } diff --git a/src/components/floor-plan/modal/setting01/dimensionLine/DimensionLineSetting.jsx b/src/components/floor-plan/modal/setting01/dimensionLine/DimensionLineSetting.jsx index 9aae056b..8bdecff8 100644 --- a/src/components/floor-plan/modal/setting01/dimensionLine/DimensionLineSetting.jsx +++ b/src/components/floor-plan/modal/setting01/dimensionLine/DimensionLineSetting.jsx @@ -190,76 +190,68 @@ export default function DimensionLineSetting(props) { } return ( - -
    -
    -

    {getMessage('modal.canvas.setting.font.plan.absorption.dimension.line')}

    -
    -
    -
    - -
    -
    -
    - {getMessage('modal.canvas.setting.font.plan.absorption.dimension.line.font.size')} -
    - setOriginPixel(e)} /> -
    - pixel -
    -
    - {getMessage('modal.canvas.setting.font.plan.absorption.dimension.line.color')} - +
    +
    + {getMessage('modal.canvas.setting.font.plan.absorption.dimension.line.font.size')} +
    + setOriginPixel(e)} />
    + pixel
    -
    -
    {getMessage('modal.canvas.setting.font.plan.absorption.dimension.display')}
    -
    -
    -
    - - 9,999 - - -
    -
    -
    -
    -
    - +
    + {getMessage('modal.canvas.setting.font.plan.absorption.dimension.line.color')} +
    -
    -
    +
    +
    {getMessage('modal.canvas.setting.font.plan.absorption.dimension.display')}
    +
    +
    +
    + + 9,999 + + +
    +
    +
    +
    +
    + +
    + ) } diff --git a/src/components/floor-plan/modal/setting01/planSize/PlanSizeSetting.jsx b/src/components/floor-plan/modal/setting01/planSize/PlanSizeSetting.jsx index 708897c0..629b45d0 100644 --- a/src/components/floor-plan/modal/setting01/planSize/PlanSizeSetting.jsx +++ b/src/components/floor-plan/modal/setting01/planSize/PlanSizeSetting.jsx @@ -46,66 +46,62 @@ export default function PlanSizeSetting(props) { const changeInput = (value, e) => { const { name } = e.target + if (Number(value) > 100000) { + value = 100000 + } + setPlanSizeSettingMode((prev) => { return { ...prev, - [name]: Number(value), + [name]: Number(value) / 10, } }) } return ( - -
    -
    -

    {getMessage('modal.canvas.setting.font.plan.absorption.plan.size.setting')}

    -
    -
    -
    -
    - {getMessage('common.horizon')} -
    - onlyNumberInputChange(e, changeInput)} - /> -
    - mm -
    -
    - {getMessage('common.vertical')} -
    - onlyNumberInputChange(e, changeInput)} - /> -
    - mm -
    -
    -
    - -
    -
    -
    -
    +
    ) } diff --git a/src/components/floor-plan/modal/wallLineOffset/WallLineOffsetSetting.jsx b/src/components/floor-plan/modal/wallLineOffset/WallLineOffsetSetting.jsx index 5e01918d..09c847e7 100644 --- a/src/components/floor-plan/modal/wallLineOffset/WallLineOffsetSetting.jsx +++ b/src/components/floor-plan/modal/wallLineOffset/WallLineOffsetSetting.jsx @@ -39,35 +39,27 @@ export default function WallLineOffsetSetting({ id, pos = { x: 50, y: 230 } }) { } return ( - -
    -
    -

    {getMessage('modal.wallline.offset.setting')}

    - + ))} +
    +
    +
    {getMessage('setting')}
    + {type === TYPES.WALL_LINE_EDIT && } + {type === TYPES.OFFSET && } +
    +
    +
    -
    -
    - {buttonMenu.map((item) => ( - - ))} -
    -
    -
    {getMessage('setting')}
    - {type === TYPES.WALL_LINE_EDIT && } - {type === TYPES.OFFSET && } -
    -
    - -
    -
    -
    -
    +
    ) } diff --git a/src/components/floor-plan/modal/wallLineOffset/type/Offset.jsx b/src/components/floor-plan/modal/wallLineOffset/type/Offset.jsx index 4e7545cb..76f09cc7 100644 --- a/src/components/floor-plan/modal/wallLineOffset/type/Offset.jsx +++ b/src/components/floor-plan/modal/wallLineOffset/type/Offset.jsx @@ -23,7 +23,7 @@ export default function Offset({ length1Ref, arrow1Ref, currentWallLineRef }) { const keyDown = (e) => { if (currentWallLineRef.current === null) { - alert('보조선을 먼저 선택하세요') + // alert('보조선을 먼저 선택하세요') return } diff --git a/src/components/footer/PromisePopup.jsx b/src/components/footer/PromisePopup.jsx new file mode 100644 index 00000000..feb400e1 --- /dev/null +++ b/src/components/footer/PromisePopup.jsx @@ -0,0 +1,71 @@ +import React, { useEffect } from 'react' +import { popSpinnerState, promisePopupState } from '@/store/popupAtom' +import { useRecoilState } from 'recoil' +import WithDraggable from '../common/draggable/WithDraggable' +import { useMessage } from '@/hooks/useMessage' + +export default function PromisePopup() { + const { getMessage } = useMessage() + const [promisePopupStore, setPromisePopupStore] = useRecoilState(promisePopupState) + const [popSpinnerStore, setPopSpinnerStore] = useRecoilState(popSpinnerState) + + const handleSpinner = () => { + setPopSpinnerStore(true) + setTimeout(() => { + setPopSpinnerStore(false) + }, 1000) + } + + return ( + + setPromisePopupStore(false)} /> + + +
    + {getMessage('modal.image.load.size.rotate')} + +
    +
    +
    +
    + + +
    +
    +
    + + +
    +
    + +
    +
    +
    +
    +
    + + +
    +
    + +
    + +
    +
    +
    +
    +
    + +
    +
    +
    + ) +} diff --git a/src/components/header/Header.jsx b/src/components/header/Header.jsx index ab6b74b7..f524f8cd 100644 --- a/src/components/header/Header.jsx +++ b/src/components/header/Header.jsx @@ -2,13 +2,13 @@ import { Fragment, useCallback, useContext, useEffect, useState } from 'react' import Link from 'next/link' -import { usePathname } from 'next/navigation' +import { usePathname, useRouter } from 'next/navigation' import { useRecoilState, useRecoilValue, useResetRecoilState } from 'recoil' import { dimmedStore, sessionStore } from '@/store/commonAtom' import { useMessage } from '@/hooks/useMessage' -import { logout } from '@/lib/authActions' +import { checkSession, logout } from '@/lib/authActions' import QSelectBox from '@/components/common/select/QSelectBox' @@ -38,6 +38,7 @@ export const ToggleonMouse = (e, act, target) => { export default function Header(props) { const [userInfoModal, setUserInfoModal] = useState(false) + const router = useRouter() const [stuffSearch, setStuffSearch] = useRecoilState(stuffSearchState) @@ -177,6 +178,7 @@ export default function Header(props) { { // moveHome() removeStuffRecoil(menu) @@ -202,6 +204,7 @@ export default function Header(props) { { removeStuffRecoil(m) }} @@ -265,6 +268,7 @@ export default function Header(props) { code: 'DELETE', }) logout() + router.replace('/login', undefined, { shallow: true }) }} > {getMessage('header.logout')} diff --git a/src/components/main/ChangePasswordPop.jsx b/src/components/main/ChangePasswordPop.jsx index b0d99d2c..54075153 100644 --- a/src/components/main/ChangePasswordPop.jsx +++ b/src/components/main/ChangePasswordPop.jsx @@ -1,4 +1,4 @@ -import React from 'react' +import { useContext } from 'react' import { useMessage } from '@/hooks/useMessage' import { useForm } from 'react-hook-form' import { sessionStore } from '@/store/commonAtom' @@ -7,10 +7,13 @@ import { useAxios } from '@/hooks/useAxios' import { globalLocaleStore } from '@/store/localeAtom' import { logout, setSession, login } from '@/lib/authActions' import { useSwal } from '@/hooks/useSwal' +import { QcastContext } from '@/app/QcastProvider' export default function ChangePasswordPop(props) { const globalLocaleState = useRecoilValue(globalLocaleStore) + const { setIsGlobalLoading } = useContext(QcastContext) + const { swalFire } = useSwal() const { patch } = useAxios(globalLocaleState) const { getMessage } = useMessage() @@ -98,9 +101,11 @@ export default function ChangePasswordPop(props) { chgPwd: _password1, } + setIsGlobalLoading(true) await patch({ url: '/api/login/v1.0/user/change-password', data: param }) .then((res) => { if (res?.result?.code === 200) { + setIsGlobalLoading(false) if (res?.result?.resultCode === 'S') { swalFire({ text: getMessage('main.popup.login.success'), @@ -114,14 +119,20 @@ export default function ChangePasswordPop(props) { }, }) } else { - alert(res?.result?.resultMsg) + swalFire({ + text: getMessage(res?.result?.resultMsg), + type: 'alert', + icon: 'error', + }) } } else { + setIsGlobalLoading(false) logout() console.log('code not 200 error') } }) .catch((error) => { + setIsGlobalLoading(false) logout() console.log('catch::::::::', error) }) diff --git a/src/components/main/MainContents.jsx b/src/components/main/MainContents.jsx index 2985484e..6d6ccd82 100644 --- a/src/components/main/MainContents.jsx +++ b/src/components/main/MainContents.jsx @@ -12,13 +12,10 @@ import { globalLocaleStore } from '@/store/localeAtom' import { queryStringFormatter } from '@/util/common-utils' import { useMainContentsController } from '@/hooks/main/useMainContentsController' import { QcastContext } from '@/app/QcastProvider' -import { useSwal } from '@/hooks/useSwal' import { handleFileDown } from '@/util/board-utils' export default function MainContents({ setFaqOpen, setFaqModalNoticeNo }) { - const { swalFire } = useSwal() - const { getMessage } = useMessage() const router = useRouter() const globalLocaleState = useRecoilValue(globalLocaleStore) @@ -33,7 +30,7 @@ export default function MainContents({ setFaqOpen, setFaqModalNoticeNo }) { const { fetchObjectList, initObjectList } = useMainContentsController() //첨부파일 - const [boardList, setBoardList] = useState([]) + const [fileList, setFileList] = useState([]) useEffect(() => { fetchObjectList() fetchNoticeList() @@ -62,9 +59,7 @@ export default function MainContents({ setFaqOpen, setFaqModalNoticeNo }) { if (resultData) { if (resultData.result.code === 200) { - setBoardList(resultData.data) - } else { - alert(resultData.result.message) + setFileList(resultData.data) } } } @@ -204,12 +199,12 @@ export default function MainContents({ setFaqOpen, setFaqModalNoticeNo }) {
    )} - - {boardList.length > 0 ? ( + + {fileList.length > 0 ? (
    - {boardList?.map((board) => ( - ))}
    diff --git a/src/components/management/Plan.jsx b/src/components/management/Plan.jsx deleted file mode 100644 index 0a627cc5..00000000 --- a/src/components/management/Plan.jsx +++ /dev/null @@ -1,7 +0,0 @@ -export default function Plan() { - return ( - <> -

    Management Plan

    - - ) -} diff --git a/src/components/management/Stuff.jsx b/src/components/management/Stuff.jsx index 0a3be3ee..c1835874 100644 --- a/src/components/management/Stuff.jsx +++ b/src/components/management/Stuff.jsx @@ -75,7 +75,10 @@ export default function Stuff() { type: 'alert', }) } catch (err) { - alert(getMessage('stuff.detail.header.failCopy')) + swalFire({ + text: getMessage('stuff.detail.header.failCopy'), + type: 'alert', + }) } finally { textArea.remove() } @@ -298,7 +301,6 @@ export default function Stuff() { } else if (stuffSearchParams?.code === 'E') { stuffSearchParams.startRow = (stuffSearch.pageNo - 1) * stuffSearchParams.pageSize + 1 stuffSearchParams.endRow = stuffSearchParams.pageNo * stuffSearchParams.pageSize - stuffSearchParams.schSortType = defaultSortType stuffSearchParams.pageNo = stuffSearchParams.pageNo if (!stuffSearchParams.saleStoreId) { diff --git a/src/components/management/StuffDetail.jsx b/src/components/management/StuffDetail.jsx index 6a2ea628..9f9dfdbf 100644 --- a/src/components/management/StuffDetail.jsx +++ b/src/components/management/StuffDetail.jsx @@ -2,8 +2,7 @@ import { useState, useEffect, useRef, useContext } from 'react' import { useRouter, useSearchParams } from 'next/navigation' -import { Button } from '@nextui-org/react' -import Select, { components } from 'react-select' +import Select from 'react-select' import { useAxios } from '@/hooks/useAxios' import { globalLocaleStore } from '@/store/localeAtom' import { isEmptyArray, isNotEmptyArray, isObjectNotEmpty, queryStringFormatter } from '@/util/common-utils' @@ -38,7 +37,7 @@ export default function StuffDetail() { const [showButton, setShowButton] = useState('') //임시저장, 저장, 삭제 버튼 컨트롤 - const { setMenuNumber } = useCanvasMenu() + const { setSelectedMenu } = useCanvasMenu() //공통코드 const { commonCode, findCommonCode } = useCommonCode() @@ -76,7 +75,7 @@ export default function StuffDetail() { standardWindSpeedId: '', //기준풍속 verticalSnowCover: '', //수직적설량 coldRegionFlg: false, //한랭지대책시행(true : 1 / false : 0) - surfaceType: 'Ⅲ・Ⅳ', //면조도구분(Ⅲ・Ⅳ / Ⅱ) + surfaceType: '', //면조도구분(Ⅲ・Ⅳ / Ⅱ) saltAreaFlg: false, //염해지역용아이템사용 (true : 1 / false : 0) installHeight: '', //설치높이 conType: '0', //계약조건(잉여 / 전량) @@ -95,6 +94,7 @@ export default function StuffDetail() { const [selectObjectStatusId, setSelectObjectStatusId] = useState('0') //신축기축 선택값 const [windSpeedList, setWindSpeedList] = useState([]) //기준 풍속 공통코드 리스트 + const [surfaceTypeList, setSurfaceTypeList] = useState([]) //면조도도 공통코드 리스트 const [prefCodeList, setPrefCodeList] = useState([]) //도도부현 코트 리스트 const [prefValue, setPrefValue] = useState('') const [saleStoreList, setSaleStoreList] = useState([]) // 판매점 리스트 @@ -106,7 +106,6 @@ export default function StuffDetail() { const [areaIdList, setAreaIdList] = useState([]) //발전시뮬레이션 리스트 - const [isFormValid, setIsFormValid] = useState(false) //임시저장, 진짜저장 버튼 컨트롤 const [showAddressButtonValid, setShowAddressButtonValid] = useState(false) //주소검색팝업 활성화 컨트롤 const [showDesignRequestButtonValid, setShowDesignRequestButtonValid] = useState(false) //설계의뢰팝업 활성화 컨트롤 const [showWindSpeedButtonValid, setShowWindSpeedButtonValid] = useState(false) //풍속선택팝업 활성화 컨트롤 @@ -141,6 +140,7 @@ export default function StuffDetail() { headerName: getMessage('stuff.detail.planGridHeader.moduleModel'), flex: 1, wrapText: true, + autoHeight: true, cellStyle: { alignItems: 'flex-start' /* 좌측정렬*/, cursor: 'pointer' }, cellRenderer: (params) => { let origin = params.value @@ -228,9 +228,8 @@ export default function StuffDetail() { }, { // 가대 - // field: 'supportMethodIdMulti', - field: 'standTypeNo', - headerName: getMessage('stuff.detail.planGridHeader.standTypeNo'), + field: 'supportMethodIdMulti', + headerName: getMessage('stuff.detail.planGridHeader.supportMethodIdMulti'), wrapText: true, autoHeight: true, cellStyle: { alignItems: 'flex-start' /* 좌측정렬*/, cursor: 'pointer' }, @@ -284,32 +283,31 @@ export default function StuffDetail() { autoHeight: true, cellStyle: { justifyContent: 'center' }, cellRenderer: (params) => { - let buttonStyle = '' - let buttonStyle2 = '' + let estimateDetailButtonStyle = '' + let docDownButtonStyle = '' if (params.value == null) { - buttonStyle = 'none' - buttonStyle2 = 'none' + estimateDetailButtonStyle = 'none' + docDownButtonStyle = 'none' } else { - if (params?.data?.createSaleStoreId === 'T01') { - if (session?.storeId !== 'T01') { - buttonStyle = 'none' - } + if (params?.data?.createSaleStoreId === 'T01' && session?.storeId !== 'T01') { + estimateDetailButtonStyle = 'none' } - if (params?.data?.tempFlg === '1') { - buttonStyle2 = 'none' + if (params?.data?.tempFlg === '1' || !params?.data?.docNo) { + docDownButtonStyle = 'none' } } + return ( <>
    - {/* {!isFormValid ? ( */} - - {/* ) : ( */} - + - {/* )} */} + +
    @@ -1928,7 +1966,6 @@ export default function StuffDetail() {
    - +
    {getMessage('stuff.detail.btn.addressPop.guide')}
    @@ -2065,9 +2102,9 @@ export default function StuffDetail() { >
    {getMessage('stuff.detail.standardWindSpeedIdSpan')} - +
    @@ -2101,34 +2138,26 @@ export default function StuffDetail() {
    -
    -
    - { - handleRadioChange(e) - }} - /> - + {surfaceTypeList.length > 0 && ( +
    + {surfaceTypeList.map((option, index) => ( +
    + { + handleRadioChange(e) + }} + /> + +
    + ))}
    -
    - { - handleRadioChange(e) - }} - /> - -
    -
    + )}
    @@ -2186,15 +2215,12 @@ export default function StuffDetail() {
    - {/* {!isFormValid ? ( */} - - {/* ) : ( */} - + - {/* )} */} + - - + +
    ) : ( <>
    - {/* {!isFormValid ? ( */} - - {/* ) : ( */} - + - {/* )} */} + + ) : null}
    @@ -2383,7 +2411,6 @@ export default function StuffDetail() { <>
    - +
    {getMessage('stuff.detail.btn.addressPop.guide')}
    @@ -2649,9 +2674,9 @@ export default function StuffDetail() { >
    {getMessage('stuff.detail.standardWindSpeedIdSpan')} - +
    @@ -2689,35 +2714,25 @@ export default function StuffDetail() {
    -
    -
    - { - handleRadioChange(e) - }} - /> - + {surfaceTypeList.length > 0 && ( +
    + {surfaceTypeList.map((option, index) => ( +
    + { + handleRadioChange(e) + }} + /> + +
    + ))}
    -
    - { - handleRadioChange(e) - }} - /> - -
    -
    - + )}
    @@ -2824,26 +2839,23 @@ export default function StuffDetail() { > {getMessage('stuff.detail.btn.moveList')} - - + +
    ) : ( <>
    - {/* {!isFormValid ? ( */} - - {/* ) : ( */} - + - {/* )} */} +
    - {/* - - */}
    - - ) -} diff --git a/src/components/simulator/Simulator.jsx b/src/components/simulator/Simulator.jsx index f7f09969..6683ff9e 100644 --- a/src/components/simulator/Simulator.jsx +++ b/src/components/simulator/Simulator.jsx @@ -12,11 +12,10 @@ import { pwrGnrSimTypeState } from '@/store/simulatorAtom' import { useAxios } from '@/hooks/useAxios' import { useMessage } from '@/hooks/useMessage' -import { useCanvasMenu } from '@/hooks/common/useCanvasMenu' import { convertNumberToPriceDecimal } from '@/util/common-utils' import { usePlan } from '@/hooks/usePlan' -import { usePopup, closeAll } from '@/hooks/usePopup' +import { usePopup } from '@/hooks/usePopup' import { QcastContext } from '@/app/QcastProvider' @@ -31,7 +30,6 @@ export default function Simulator() { const chartRef = useRef(null) // 캔버스 메뉴 넘버 셋팅 - const { setMenuNumber } = useCanvasMenu() const { closeAll } = usePopup() const { get } = useAxios() @@ -120,7 +118,6 @@ export default function Simulator() { fetchSimulatorNotice() setPwrGnrSimType('D') setPwrRecoil({ ...pwrRecoil, type: 'D' }) - setMenuNumber(6) closeAll() } }, [objectNo, pid, selectedPlan]) diff --git a/src/components/ui/ObjectPlacement.jsx b/src/components/ui/ObjectPlacement.jsx index f7a73a5c..d03f2a1e 100644 --- a/src/components/ui/ObjectPlacement.jsx +++ b/src/components/ui/ObjectPlacement.jsx @@ -1,5 +1,4 @@ import React, { useCallback, useEffect, useRef, useState } from 'react' -import { Button, Input } from '@nextui-org/react' import { useRecoilState, useSetRecoilState } from 'recoil' import { modalState } from '@/store/modalAtom' import { fabric } from 'fabric' @@ -19,7 +18,7 @@ const ObjectPlacement = ({ canvas }) => { const [batchType, setBatchType] = useState(BATCH_TYPE.OPENING) // free or dimension 프리 / 치수 - const [inputType, setInputType] = useState(INPUT_TYPE.FREE) + const [inputType, setinputType] = useState(INPUT_TYPE.FREE) const handleSave = () => { setMode(batchType) @@ -38,7 +37,7 @@ const ObjectPlacement = ({ canvas }) => {
    - - +
    @@ -64,7 +63,7 @@ const ObjectPlacement = ({ canvas }) => {