From 4927c0b06636ea83a4cf16295f70461584e5625d Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Fri, 1 Nov 2024 13:21:55 +0900 Subject: [PATCH 01/51] feat: Add floor-plan image load feature --- .../placementShape/PlacementShapeSetting.jsx | 9 +- src/hooks/common/useRefFiles.js | 11 + yarn.lock | 595 +++++++++++++----- 3 files changed, 461 insertions(+), 154 deletions(-) create mode 100644 src/hooks/common/useRefFiles.js diff --git a/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx b/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx index 99b72eb4..539dbdf1 100644 --- a/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx +++ b/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx @@ -9,6 +9,7 @@ import { useAxios } from '@/hooks/useAxios' import { useSwal } from '@/hooks/useSwal' import { usePopup } from '@/hooks/usePopup' import { basicSettingState } from '@/store/settingAtom' +import useRefFiles from '@/hooks/common/useRefFiles' export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, setShowPlaceShapeModal }) { const [objectNo, setObjectNo] = useState('test123241008001') // 후에 삭제 필요 @@ -18,7 +19,7 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set const [canvasSetting, setCanvasSetting] = useRecoilState(canvasSettingState) const { closePopup } = usePopup() const [basicSetting, setBasicSettings] = useRecoilState(basicSettingState) - const [image, setImage] = useState(null) + const { refImage, setRefImage } = useRefFiles() const { getMessage } = useMessage() const { get, post } = useAxios() @@ -489,11 +490,11 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set {getMessage('common.input.file.load')} - setImage(e.target.files[0])} /> + setRefImage(e.target.files[0])} />
- - {image && } + + {refImage && }
diff --git a/src/hooks/common/useRefFiles.js b/src/hooks/common/useRefFiles.js new file mode 100644 index 00000000..8cb046d5 --- /dev/null +++ b/src/hooks/common/useRefFiles.js @@ -0,0 +1,11 @@ +import { useState } from 'react' + +export default function useRefFiles() { + const [refImage, setRefImage] = useState(null) + const converterUrl = process.env.NEXT_PUBLIC_CONVERTER_API_URL + + return { + refImage, + setRefImage, + } +} diff --git a/yarn.lock b/yarn.lock index f2bcf8b4..a167fa9d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -223,14 +223,7 @@ dependencies: regenerator-runtime "^0.14.0" -"@babel/runtime@^7.20.13": - version "7.25.0" - resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.0.tgz" - integrity sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw== - dependencies: - regenerator-runtime "^0.14.0" - -"@babel/runtime@^7.24.8": +"@babel/runtime@^7.20.13", "@babel/runtime@^7.24.8": version "7.25.0" resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.0.tgz" integrity sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw== @@ -534,6 +527,21 @@ resolved "https://registry.npmjs.org/@js-joda/core/-/core-5.6.3.tgz" integrity sha512-T1rRxzdqkEXcou0ZprN1q9yDRlvzCPLqmlNt5IIsGBzoEVgLCCYrKEwc84+TvsXuAc95VAZwtWD2zVsKPY4bcA== +"@mapbox/node-pre-gyp@^1.0.0": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz#417db42b7f5323d79e93b34a6d7a2a12c0df43fa" + integrity sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ== + dependencies: + detect-libc "^2.0.0" + https-proxy-agent "^5.0.0" + make-dir "^3.1.0" + node-fetch "^2.6.7" + nopt "^5.0.0" + npmlog "^5.0.1" + rimraf "^3.0.2" + semver "^7.3.5" + tar "^6.1.11" + "@next/env@14.2.3": version "14.2.3" resolved "https://registry.npmjs.org/@next/env/-/env-14.2.3.tgz" @@ -1238,7 +1246,7 @@ "@react-types/shared" "3.23.1" clsx "^1.2.1" -"@nextui-org/system@>=2.0.0", "@nextui-org/system@>=2.1.0", "@nextui-org/system@2.2.5": +"@nextui-org/system@2.2.5": version "2.2.5" resolved "https://registry.npmjs.org/@nextui-org/system/-/system-2.2.5.tgz" integrity sha512-nrX6768aiyWtpxX3OTFBIVWR+v9nlMsC3KaBinNfek97sNm7gAfTHi7q5kylE3L5yIMpNG+DclAKpuxgDQEmvw== @@ -1291,7 +1299,7 @@ "@react-types/tabs" "3.3.7" scroll-into-view-if-needed "3.0.10" -"@nextui-org/theme@>=2.1.0", "@nextui-org/theme@>=2.2.0", "@nextui-org/theme@2.2.9": +"@nextui-org/theme@2.2.9": version "2.2.9" resolved "https://registry.npmjs.org/@nextui-org/theme/-/theme-2.2.9.tgz" integrity sha512-TN2I9sMriLaj00pXsIMlg19+UHeOdjzS2JV0u4gjL14mSbQl5BYNxgbvU3gbMqkZZQ6OpwT4RnT8RS+ks6TXCw== @@ -1512,7 +1520,7 @@ "@nodelib/fs.stat" "2.0.5" run-parallel "^1.1.9" -"@nodelib/fs.stat@^2.0.2", "@nodelib/fs.stat@2.0.5": +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": version "2.0.5" resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz" integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== @@ -1645,7 +1653,7 @@ "@react-types/shared" "^3.23.1" "@swc/helpers" "^0.5.0" -"@react-aria/focus@^3.17.1", "@react-aria/focus@3.17.1": +"@react-aria/focus@3.17.1", "@react-aria/focus@^3.17.1": version "3.17.1" resolved "https://registry.npmjs.org/@react-aria/focus/-/focus-3.17.1.tgz" integrity sha512-FLTySoSNqX++u0nWZJPPN5etXY0WBxaIe/YuL/GTEeuqUIuC/2bJSaw5hlsM6T2yjy6Y/VAxBcKSdAFUlU6njQ== @@ -1667,7 +1675,7 @@ "@swc/helpers" "^0.5.0" clsx "^2.0.0" -"@react-aria/form@^3.0.5", "@react-aria/form@3.0.5": +"@react-aria/form@3.0.5", "@react-aria/form@^3.0.5": version "3.0.5" resolved "https://registry.npmjs.org/@react-aria/form/-/form-3.0.5.tgz" integrity sha512-n290jRwrrRXO3fS82MyWR+OKN7yznVesy5Q10IclSTVYHHI3VI53xtAPr/WzNjJR1um8aLhOcDNFKwnNIUUCsQ== @@ -1697,7 +1705,7 @@ "@react-types/shared" "^3.24.1" "@swc/helpers" "^0.5.0" -"@react-aria/i18n@^3.11.1", "@react-aria/i18n@3.11.1": +"@react-aria/i18n@3.11.1", "@react-aria/i18n@^3.11.1": version "3.11.1" resolved "https://registry.npmjs.org/@react-aria/i18n/-/i18n-3.11.1.tgz" integrity sha512-vuiBHw1kZruNMYeKkTGGnmPyMnM5T+gT8bz97H1FqIq1hQ6OPzmtBZ6W6l6OIMjeHI5oJo4utTwfZl495GALFQ== @@ -1725,7 +1733,7 @@ "@react-types/shared" "^3.24.1" "@swc/helpers" "^0.5.0" -"@react-aria/interactions@^3.21.3", "@react-aria/interactions@3.21.3": +"@react-aria/interactions@3.21.3", "@react-aria/interactions@^3.21.3": version "3.21.3" resolved "https://registry.npmjs.org/@react-aria/interactions/-/interactions-3.21.3.tgz" integrity sha512-BWIuf4qCs5FreDJ9AguawLVS0lV9UU+sK4CCnbCNNmYqOWY+1+gRXCsnOM32K+oMESBxilAjdHW5n1hsMqYMpA== @@ -1745,7 +1753,7 @@ "@react-types/shared" "^3.24.1" "@swc/helpers" "^0.5.0" -"@react-aria/label@^3.7.8", "@react-aria/label@3.7.8": +"@react-aria/label@3.7.8", "@react-aria/label@^3.7.8": version "3.7.8" resolved "https://registry.npmjs.org/@react-aria/label/-/label-3.7.8.tgz" integrity sha512-MzgTm5+suPA3KX7Ug6ZBK2NX9cin/RFLsv1BdafJ6CZpmUSpWnGE/yQfYUB7csN7j31OsZrD3/P56eShYWAQfg== @@ -1754,7 +1762,7 @@ "@react-types/shared" "^3.23.1" "@swc/helpers" "^0.5.0" -"@react-aria/link@^3.7.1", "@react-aria/link@3.7.1": +"@react-aria/link@3.7.1", "@react-aria/link@^3.7.1": version "3.7.1" resolved "https://registry.npmjs.org/@react-aria/link/-/link-3.7.1.tgz" integrity sha512-a4IaV50P3fXc7DQvEIPYkJJv26JknFbRzFT5MJOMgtzuhyJoQdILEUK6XHYjcSSNCA7uLgzpojArVk5Hz3lCpw== @@ -1766,7 +1774,7 @@ "@react-types/shared" "^3.23.1" "@swc/helpers" "^0.5.0" -"@react-aria/listbox@^3.12.1", "@react-aria/listbox@3.12.1": +"@react-aria/listbox@3.12.1", "@react-aria/listbox@^3.12.1": version "3.12.1" resolved "https://registry.npmjs.org/@react-aria/listbox/-/listbox-3.12.1.tgz" integrity sha512-7JiUp0NGykbv/HgSpmTY1wqhuf/RmjFxs1HZcNaTv8A+DlzgJYc7yQqFjP3ZA/z5RvJFuuIxggIYmgIFjaRYdA== @@ -1788,7 +1796,7 @@ dependencies: "@swc/helpers" "^0.5.0" -"@react-aria/menu@^3.14.1", "@react-aria/menu@3.14.1": +"@react-aria/menu@3.14.1", "@react-aria/menu@^3.14.1": version "3.14.1" resolved "https://registry.npmjs.org/@react-aria/menu/-/menu-3.14.1.tgz" integrity sha512-BYliRb38uAzq05UOFcD5XkjA5foQoXRbcH3ZufBsc4kvh79BcP1PMW6KsXKGJ7dC/PJWUwCui6QL1kUg8PqMHA== @@ -1807,7 +1815,7 @@ "@react-types/shared" "^3.23.1" "@swc/helpers" "^0.5.0" -"@react-aria/overlays@^3.22.1", "@react-aria/overlays@3.22.1": +"@react-aria/overlays@3.22.1", "@react-aria/overlays@^3.22.1": version "3.22.1" resolved "https://registry.npmjs.org/@react-aria/overlays/-/overlays-3.22.1.tgz" integrity sha512-GHiFMWO4EQ6+j6b5QCnNoOYiyx1Gk8ZiwLzzglCI4q1NY5AG2EAmfU4Z1+Gtrf2S5Y0zHbumC7rs9GnPoGLUYg== @@ -1852,7 +1860,7 @@ "@react-types/shared" "^3.23.1" "@swc/helpers" "^0.5.0" -"@react-aria/selection@^3.18.1", "@react-aria/selection@3.18.1": +"@react-aria/selection@3.18.1", "@react-aria/selection@^3.18.1": version "3.18.1" resolved "https://registry.npmjs.org/@react-aria/selection/-/selection-3.18.1.tgz" integrity sha512-GSqN2jX6lh7v+ldqhVjAXDcrWS3N4IsKXxO6L6Ygsye86Q9q9Mq9twWDWWu5IjHD6LoVZLUBCMO+ENGbOkyqeQ== @@ -1905,7 +1913,7 @@ "@react-types/shared" "^3.24.1" "@swc/helpers" "^0.5.0" -"@react-aria/ssr@^3.9.4", "@react-aria/ssr@3.9.4": +"@react-aria/ssr@3.9.4", "@react-aria/ssr@^3.9.4": version "3.9.4" resolved "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.9.4.tgz" integrity sha512-4jmAigVq409qcJvQyuorsmBR4+9r3+JEC60wC+Y0MZV0HCtTmm8D9guYXlJMdx0SSkgj0hHAyFm/HvPNFofCoQ== @@ -1965,7 +1973,7 @@ "@react-types/tabs" "^3.3.7" "@swc/helpers" "^0.5.0" -"@react-aria/textfield@^3.14.5", "@react-aria/textfield@3.14.5": +"@react-aria/textfield@3.14.5", "@react-aria/textfield@^3.14.5": version "3.14.5" resolved "https://registry.npmjs.org/@react-aria/textfield/-/textfield-3.14.5.tgz" integrity sha512-hj7H+66BjB1iTKKaFXwSZBZg88YT+wZboEXZ0DNdQB2ytzoz/g045wBItUuNi4ZjXI3P+0AOZznVMYadWBAmiA== @@ -2006,7 +2014,7 @@ "@react-types/tooltip" "^3.4.9" "@swc/helpers" "^0.5.0" -"@react-aria/utils@^3.24.1", "@react-aria/utils@3.24.1": +"@react-aria/utils@3.24.1", "@react-aria/utils@^3.24.1": version "3.24.1" resolved "https://registry.npmjs.org/@react-aria/utils/-/utils-3.24.1.tgz" integrity sha512-O3s9qhPMd6n42x9sKeJ3lhu5V1Tlnzhu6Yk8QOvDuXf7UGuUjXf9mzfHJt1dYzID4l9Fwm8toczBzPM9t0jc8Q== @@ -2028,7 +2036,7 @@ "@swc/helpers" "^0.5.0" clsx "^2.0.0" -"@react-aria/visually-hidden@^3.8.12", "@react-aria/visually-hidden@3.8.12": +"@react-aria/visually-hidden@3.8.12", "@react-aria/visually-hidden@^3.8.12": version "3.8.12" resolved "https://registry.npmjs.org/@react-aria/visually-hidden/-/visually-hidden-3.8.12.tgz" integrity sha512-Bawm+2Cmw3Xrlr7ARzl2RLtKh0lNUdJ0eNqzWcyx4c0VHUAWtThmH5l+HRqFUGzzutFZVo89SAy40BAbd0gjVw== @@ -2038,7 +2046,7 @@ "@react-types/shared" "^3.23.1" "@swc/helpers" "^0.5.0" -"@react-stately/calendar@^3.5.1", "@react-stately/calendar@3.5.1": +"@react-stately/calendar@3.5.1", "@react-stately/calendar@^3.5.1": version "3.5.1" resolved "https://registry.npmjs.org/@react-stately/calendar/-/calendar-3.5.1.tgz" integrity sha512-7l7QhqGUJ5AzWHfvZzbTe3J4t72Ht5BmhW4hlVI7flQXtfrmYkVtl3ZdytEZkkHmWGYZRW9b4IQTQGZxhtlElA== @@ -2049,7 +2057,7 @@ "@react-types/shared" "^3.23.1" "@swc/helpers" "^0.5.0" -"@react-stately/checkbox@^3.6.5", "@react-stately/checkbox@3.6.5": +"@react-stately/checkbox@3.6.5", "@react-stately/checkbox@^3.6.5": version "3.6.5" resolved "https://registry.npmjs.org/@react-stately/checkbox/-/checkbox-3.6.5.tgz" integrity sha512-IXV3f9k+LtmfQLE+DKIN41Q5QB/YBLDCB1YVx5PEdRp52S9+EACD5683rjVm8NVRDwjMi2SP6RnFRk7fVb5Azg== @@ -2060,7 +2068,7 @@ "@react-types/shared" "^3.23.1" "@swc/helpers" "^0.5.0" -"@react-stately/collections@^3.10.7", "@react-stately/collections@3.10.7": +"@react-stately/collections@3.10.7", "@react-stately/collections@^3.10.7": version "3.10.7" resolved "https://registry.npmjs.org/@react-stately/collections/-/collections-3.10.7.tgz" integrity sha512-KRo5O2MWVL8n3aiqb+XR3vP6akmHLhLWYZEmPKjIv0ghQaEebBTrN3wiEjtd6dzllv0QqcWvDLM1LntNfJ2TsA== @@ -2076,7 +2084,7 @@ "@react-types/shared" "^3.24.1" "@swc/helpers" "^0.5.0" -"@react-stately/combobox@^3.8.4", "@react-stately/combobox@3.8.4": +"@react-stately/combobox@3.8.4", "@react-stately/combobox@^3.8.4": version "3.8.4" resolved "https://registry.npmjs.org/@react-stately/combobox/-/combobox-3.8.4.tgz" integrity sha512-iLVGvKRRz0TeJXZhZyK783hveHpYA6xovOSdzSD+WGYpiPXo1QrcrNoH3AE0Z2sHtorU+8nc0j58vh5PB+m2AA== @@ -2091,7 +2099,7 @@ "@react-types/shared" "^3.23.1" "@swc/helpers" "^0.5.0" -"@react-stately/datepicker@^3.9.4", "@react-stately/datepicker@3.9.4": +"@react-stately/datepicker@3.9.4", "@react-stately/datepicker@^3.9.4": version "3.9.4" resolved "https://registry.npmjs.org/@react-stately/datepicker/-/datepicker-3.9.4.tgz" integrity sha512-yBdX01jn6gq4NIVvHIqdjBUPo+WN8Bujc4OnPw+ZnfA4jI0eIgq04pfZ84cp1LVXW0IB0VaCu1AlQ/kvtZjfGA== @@ -2112,7 +2120,7 @@ dependencies: "@swc/helpers" "^0.5.0" -"@react-stately/form@^3.0.3", "@react-stately/form@3.0.3": +"@react-stately/form@3.0.3", "@react-stately/form@^3.0.3": version "3.0.3" resolved "https://registry.npmjs.org/@react-stately/form/-/form-3.0.3.tgz" integrity sha512-92YYBvlHEWUGUpXgIaQ48J50jU9XrxfjYIN8BTvvhBHdD63oWgm8DzQnyT/NIAMzdLnhkg7vP+fjG8LjHeyIAg== @@ -2139,7 +2147,7 @@ "@react-types/shared" "^3.24.1" "@swc/helpers" "^0.5.0" -"@react-stately/list@^3.10.5", "@react-stately/list@3.10.5": +"@react-stately/list@3.10.5", "@react-stately/list@^3.10.5": version "3.10.5" resolved "https://registry.npmjs.org/@react-stately/list/-/list-3.10.5.tgz" integrity sha512-fV9plO+6QDHiewsYIhboxcDhF17GO95xepC5ki0bKXo44gr14g/LSo/BMmsaMnV+1BuGdBunB05bO4QOIaigXA== @@ -2161,7 +2169,7 @@ "@react-types/shared" "^3.24.1" "@swc/helpers" "^0.5.0" -"@react-stately/menu@^3.7.1", "@react-stately/menu@3.7.1": +"@react-stately/menu@3.7.1", "@react-stately/menu@^3.7.1": version "3.7.1" resolved "https://registry.npmjs.org/@react-stately/menu/-/menu-3.7.1.tgz" integrity sha512-mX1w9HHzt+xal1WIT2xGrTQsoLvDwuB2R1Er1MBABs//MsJzccycatcgV/J/28m6tO5M9iuFQQvLV+i1dCtodg== @@ -2171,7 +2179,7 @@ "@react-types/shared" "^3.23.1" "@swc/helpers" "^0.5.0" -"@react-stately/overlays@^3.6.7", "@react-stately/overlays@3.6.7": +"@react-stately/overlays@3.6.7", "@react-stately/overlays@^3.6.7": version "3.6.7" resolved "https://registry.npmjs.org/@react-stately/overlays/-/overlays-3.6.7.tgz" integrity sha512-6zp8v/iNUm6YQap0loaFx6PlvN8C0DgWHNlrlzMtMmNuvjhjR0wYXVaTfNoUZBWj25tlDM81ukXOjpRXg9rLrw== @@ -2189,7 +2197,7 @@ "@react-types/overlays" "^3.8.9" "@swc/helpers" "^0.5.0" -"@react-stately/radio@^3.10.4", "@react-stately/radio@3.10.4": +"@react-stately/radio@3.10.4", "@react-stately/radio@^3.10.4": version "3.10.4" resolved "https://registry.npmjs.org/@react-stately/radio/-/radio-3.10.4.tgz" integrity sha512-kCIc7tAl4L7Hu4Wt9l2jaa+MzYmAJm0qmC8G8yPMbExpWbLRu6J8Un80GZu+JxvzgDlqDyrVvyv9zFifwH/NkQ== @@ -2222,7 +2230,7 @@ "@react-types/shared" "^3.24.1" "@swc/helpers" "^0.5.0" -"@react-stately/slider@^3.5.4", "@react-stately/slider@3.5.4": +"@react-stately/slider@3.5.4", "@react-stately/slider@^3.5.4": version "3.5.4" resolved "https://registry.npmjs.org/@react-stately/slider/-/slider-3.5.4.tgz" integrity sha512-Jsf7K17dr93lkNKL9ij8HUcoM1sPbq8TvmibD6DhrK9If2lje+OOL8y4n4qreUnfMT56HCAeS9wCO3fg3eMyrw== @@ -2232,7 +2240,7 @@ "@react-types/slider" "^3.7.3" "@swc/helpers" "^0.5.0" -"@react-stately/table@^3.11.8", "@react-stately/table@3.11.8": +"@react-stately/table@3.11.8", "@react-stately/table@^3.11.8": version "3.11.8" resolved "https://registry.npmjs.org/@react-stately/table/-/table-3.11.8.tgz" integrity sha512-EdyRW3lT1/kAVDp5FkEIi1BQ7tvmD2YgniGdLuW/l9LADo0T+oxZqruv60qpUS6sQap+59Riaxl91ClDxrJnpg== @@ -2247,7 +2255,7 @@ "@react-types/table" "^3.9.5" "@swc/helpers" "^0.5.0" -"@react-stately/tabs@^3.6.6", "@react-stately/tabs@3.6.6": +"@react-stately/tabs@3.6.6", "@react-stately/tabs@^3.6.6": version "3.6.6" resolved "https://registry.npmjs.org/@react-stately/tabs/-/tabs-3.6.6.tgz" integrity sha512-sOLxorH2uqjAA+v1ppkMCc2YyjgqvSGeBDgtR/lyPSDd4CVMoTExszROX2dqG0c8il9RQvzFuufUtQWMY6PgSA== @@ -2257,7 +2265,7 @@ "@react-types/tabs" "^3.3.7" "@swc/helpers" "^0.5.0" -"@react-stately/toggle@^3.7.4", "@react-stately/toggle@3.7.4": +"@react-stately/toggle@3.7.4", "@react-stately/toggle@^3.7.4": version "3.7.4" resolved "https://registry.npmjs.org/@react-stately/toggle/-/toggle-3.7.4.tgz" integrity sha512-CoYFe9WrhLkDP4HGDpJYQKwfiYCRBAeoBQHv+JWl5eyK61S8xSwoHsveYuEZ3bowx71zyCnNAqWRrmNOxJ4CKA== @@ -2275,7 +2283,7 @@ "@react-types/checkbox" "^3.8.3" "@swc/helpers" "^0.5.0" -"@react-stately/tooltip@^3.4.9", "@react-stately/tooltip@3.4.9": +"@react-stately/tooltip@3.4.9", "@react-stately/tooltip@^3.4.9": version "3.4.9" resolved "https://registry.npmjs.org/@react-stately/tooltip/-/tooltip-3.4.9.tgz" integrity sha512-P7CDJsdoKarz32qFwf3VNS01lyC+63gXpDZG31pUu+EO5BeQd4WKN/AH1Beuswpr4GWzxzFc1aXQgERFGVzraA== @@ -2284,7 +2292,7 @@ "@react-types/tooltip" "^3.4.9" "@swc/helpers" "^0.5.0" -"@react-stately/tree@^3.8.1", "@react-stately/tree@3.8.1": +"@react-stately/tree@3.8.1", "@react-stately/tree@^3.8.1": version "3.8.1" resolved "https://registry.npmjs.org/@react-stately/tree/-/tree-3.8.1.tgz" integrity sha512-LOdkkruJWch3W89h4B/bXhfr0t0t1aRfEp+IMrrwdRAl23NaPqwl5ILHs4Xu5XDHqqhg8co73pHrJwUyiTWEjw== @@ -2295,7 +2303,7 @@ "@react-types/shared" "^3.23.1" "@swc/helpers" "^0.5.0" -"@react-stately/utils@^3.10.1", "@react-stately/utils@3.10.1": +"@react-stately/utils@3.10.1", "@react-stately/utils@^3.10.1": version "3.10.1" resolved "https://registry.npmjs.org/@react-stately/utils/-/utils-3.10.1.tgz" integrity sha512-VS/EHRyicef25zDZcM/ClpzYMC5i2YGN6uegOeQawmgfGjb02yaCX0F0zR69Pod9m2Hr3wunTbtpgVXvYbZItg== @@ -2309,7 +2317,7 @@ dependencies: "@swc/helpers" "^0.5.0" -"@react-stately/virtualizer@^3.7.1", "@react-stately/virtualizer@3.7.1": +"@react-stately/virtualizer@3.7.1", "@react-stately/virtualizer@^3.7.1": version "3.7.1" resolved "https://registry.npmjs.org/@react-stately/virtualizer/-/virtualizer-3.7.1.tgz" integrity sha512-voHgE6EQ+oZaLv6u2umKxakvIKNkCQuUihqKACTjdslp7SJh4Mvs3oLBI0hf0JOh+rCcFIKDvQtFwy1fXFRYBA== @@ -2325,7 +2333,7 @@ dependencies: "@react-types/shared" "^3.23.1" -"@react-types/breadcrumbs@^3.7.5", "@react-types/breadcrumbs@3.7.5": +"@react-types/breadcrumbs@3.7.5", "@react-types/breadcrumbs@^3.7.5": version "3.7.5" resolved "https://registry.npmjs.org/@react-types/breadcrumbs/-/breadcrumbs-3.7.5.tgz" integrity sha512-lV9IDYsMiu2TgdMIjEmsOE0YWwjb3jhUNK1DCZZfq6uWuiHLgyx2EncazJBUWSjHJ4ta32j7xTuXch+8Ai6u/A== @@ -2333,7 +2341,7 @@ "@react-types/link" "^3.5.5" "@react-types/shared" "^3.23.1" -"@react-types/button@^3.9.4", "@react-types/button@3.9.4": +"@react-types/button@3.9.4", "@react-types/button@^3.9.4": version "3.9.4" resolved "https://registry.npmjs.org/@react-types/button/-/button-3.9.4.tgz" integrity sha512-raeQBJUxBp0axNF74TXB8/H50GY8Q3eV6cEKMbZFP1+Dzr09Ngv0tJBeW0ewAxAguNH5DRoMUAUGIXtSXskVdA== @@ -2347,7 +2355,7 @@ dependencies: "@react-types/shared" "^3.24.1" -"@react-types/calendar@^3.4.6", "@react-types/calendar@3.4.6": +"@react-types/calendar@3.4.6", "@react-types/calendar@^3.4.6": version "3.4.6" resolved "https://registry.npmjs.org/@react-types/calendar/-/calendar-3.4.6.tgz" integrity sha512-WSntZPwtvsIYWvBQRAPvuCn55UTJBZroTvX0vQvWykJRQnPAI20G1hMQ3dNsnAL+gLZUYxBXn66vphmjUuSYew== @@ -2355,7 +2363,7 @@ "@internationalized/date" "^3.5.4" "@react-types/shared" "^3.23.1" -"@react-types/checkbox@^3.8.1", "@react-types/checkbox@3.8.1": +"@react-types/checkbox@3.8.1", "@react-types/checkbox@^3.8.1": version "3.8.1" resolved "https://registry.npmjs.org/@react-types/checkbox/-/checkbox-3.8.1.tgz" integrity sha512-5/oVByPw4MbR/8QSdHCaalmyWC71H/QGgd4aduTJSaNi825o+v/hsN2/CH7Fq9atkLKsC8fvKD00Bj2VGaKriQ== @@ -2369,14 +2377,14 @@ dependencies: "@react-types/shared" "^3.24.1" -"@react-types/combobox@^3.11.1", "@react-types/combobox@3.11.1": +"@react-types/combobox@3.11.1", "@react-types/combobox@^3.11.1": version "3.11.1" resolved "https://registry.npmjs.org/@react-types/combobox/-/combobox-3.11.1.tgz" integrity sha512-UNc3OHt5cUt5gCTHqhQIqhaWwKCpaNciD8R7eQazmHiA9fq8ROlV+7l3gdNgdhJbTf5Bu/V5ISnN7Y1xwL3zqQ== dependencies: "@react-types/shared" "^3.23.1" -"@react-types/datepicker@^3.7.4", "@react-types/datepicker@3.7.4": +"@react-types/datepicker@3.7.4", "@react-types/datepicker@^3.7.4": version "3.7.4" resolved "https://registry.npmjs.org/@react-types/datepicker/-/datepicker-3.7.4.tgz" integrity sha512-ZfvgscvNzBJpYyVWg3nstJtA/VlWLwErwSkd1ivZYam859N30w8yH+4qoYLa6FzWLCFlrsRHyvtxlEM7lUAt5A== @@ -2394,7 +2402,7 @@ "@react-types/overlays" "^3.8.9" "@react-types/shared" "^3.24.1" -"@react-types/grid@^3.2.6", "@react-types/grid@3.2.6": +"@react-types/grid@3.2.6", "@react-types/grid@^3.2.6": version "3.2.6" resolved "https://registry.npmjs.org/@react-types/grid/-/grid-3.2.6.tgz" integrity sha512-XfHenL2jEBUYrhKiPdeM24mbLRXUn79wVzzMhrNYh24nBwhsPPpxF+gjFddT3Cy8dt6tRInfT6pMEu9nsXwaHw== @@ -2408,7 +2416,7 @@ dependencies: "@react-types/shared" "^3.24.1" -"@react-types/link@^3.5.5", "@react-types/link@3.5.5": +"@react-types/link@3.5.5", "@react-types/link@^3.5.5": version "3.5.5" resolved "https://registry.npmjs.org/@react-types/link/-/link-3.5.5.tgz" integrity sha512-G6P5WagHDR87npN7sEuC5IIgL1GsoY4WFWKO4734i2CXRYx24G9P0Su3AX4GA3qpspz8sK1AWkaCzBMmvnunfw== @@ -2422,7 +2430,7 @@ dependencies: "@react-types/shared" "^3.24.1" -"@react-types/menu@^3.9.9", "@react-types/menu@3.9.9": +"@react-types/menu@3.9.9", "@react-types/menu@^3.9.9": version "3.9.9" resolved "https://registry.npmjs.org/@react-types/menu/-/menu-3.9.9.tgz" integrity sha512-FamUaPVs1Fxr4KOMI0YcR2rYZHoN7ypGtgiEiJ11v/tEPjPPGgeKDxii0McCrdOkjheatLN1yd2jmMwYj6hTDg== @@ -2430,7 +2438,7 @@ "@react-types/overlays" "^3.8.7" "@react-types/shared" "^3.23.1" -"@react-types/overlays@^3.8.7", "@react-types/overlays@3.8.7": +"@react-types/overlays@3.8.7", "@react-types/overlays@^3.8.7": version "3.8.7" resolved "https://registry.npmjs.org/@react-types/overlays/-/overlays-3.8.7.tgz" integrity sha512-zCOYvI4at2DkhVpviIClJ7bRrLXYhSg3Z3v9xymuPH3mkiuuP/dm8mUCtkyY4UhVeUTHmrQh1bzaOP00A+SSQA== @@ -2444,20 +2452,27 @@ dependencies: "@react-types/shared" "^3.24.1" -"@react-types/progress@^3.5.4", "@react-types/progress@3.5.4": +"@react-types/progress@3.5.4", "@react-types/progress@^3.5.4": version "3.5.4" resolved "https://registry.npmjs.org/@react-types/progress/-/progress-3.5.4.tgz" integrity sha512-JNc246sTjasPyx5Dp7/s0rp3Bz4qlu4LrZTulZlxWyb53WgBNL7axc26CCi+I20rWL9+c7JjhrRxnLl/1cLN5g== dependencies: "@react-types/shared" "^3.23.1" -"@react-types/radio@^3.8.1", "@react-types/radio@3.8.1": +"@react-types/radio@3.8.1", "@react-types/radio@^3.8.1": version "3.8.1" resolved "https://registry.npmjs.org/@react-types/radio/-/radio-3.8.1.tgz" integrity sha512-bK0gio/qj1+0Ldu/3k/s9BaOZvnnRgvFtL3u5ky479+aLG5qf1CmYed3SKz8ErZ70JkpuCSrSwSCFf0t1IHovw== dependencies: "@react-types/shared" "^3.23.1" +"@react-types/select@3.9.4": + version "3.9.4" + resolved "https://registry.npmjs.org/@react-types/select/-/select-3.9.4.tgz" + integrity sha512-xI7dnOW2st91fPPcv6hdtrTdcfetYiqZuuVPZ5TRobY7Q10/Zqqe/KqtOw1zFKUj9xqNJe4Ov3xP5GSdcO60Eg== + dependencies: + "@react-types/shared" "^3.23.1" + "@react-types/select@^3.9.6": version "3.9.6" resolved "https://registry.npmjs.org/@react-types/select/-/select-3.9.6.tgz" @@ -2465,14 +2480,7 @@ dependencies: "@react-types/shared" "^3.24.1" -"@react-types/select@3.9.4": - version "3.9.4" - resolved "https://registry.npmjs.org/@react-types/select/-/select-3.9.4.tgz" - integrity sha512-xI7dnOW2st91fPPcv6hdtrTdcfetYiqZuuVPZ5TRobY7Q10/Zqqe/KqtOw1zFKUj9xqNJe4Ov3xP5GSdcO60Eg== - dependencies: - "@react-types/shared" "^3.23.1" - -"@react-types/shared@^3.23.1", "@react-types/shared@3.23.1": +"@react-types/shared@3.23.1", "@react-types/shared@^3.23.1": version "3.23.1" resolved "https://registry.npmjs.org/@react-types/shared/-/shared-3.23.1.tgz" integrity sha512-5d+3HbFDxGZjhbMBeFHRQhexMFt4pUce3okyRtUVKbbedQFUrtXSBg9VszgF2RTeQDKDkMCIQDtz5ccP/Lk1gw== @@ -2496,7 +2504,7 @@ dependencies: "@react-types/shared" "^3.24.1" -"@react-types/table@^3.9.5", "@react-types/table@3.9.5": +"@react-types/table@3.9.5", "@react-types/table@^3.9.5": version "3.9.5" resolved "https://registry.npmjs.org/@react-types/table/-/table-3.9.5.tgz" integrity sha512-fgM2j9F/UR4Anmd28CueghCgBwOZoCVyN8fjaIFPd2MN4gCwUUfANwxLav65gZk4BpwUXGoQdsW+X50L3555mg== @@ -2504,21 +2512,21 @@ "@react-types/grid" "^3.2.6" "@react-types/shared" "^3.23.1" -"@react-types/tabs@^3.3.7", "@react-types/tabs@3.3.7": +"@react-types/tabs@3.3.7", "@react-types/tabs@^3.3.7": version "3.3.7" resolved "https://registry.npmjs.org/@react-types/tabs/-/tabs-3.3.7.tgz" integrity sha512-ZdLe5xOcFX6+/ni45Dl2jO0jFATpTnoSqj6kLIS/BYv8oh0n817OjJkLf+DS3CLfNjApJWrHqAk34xNh6nRnEg== dependencies: "@react-types/shared" "^3.23.1" -"@react-types/textfield@^3.9.3", "@react-types/textfield@3.9.3": +"@react-types/textfield@3.9.3", "@react-types/textfield@^3.9.3": version "3.9.3" resolved "https://registry.npmjs.org/@react-types/textfield/-/textfield-3.9.3.tgz" integrity sha512-DoAY6cYOL0pJhgNGI1Rosni7g72GAt4OVr2ltEx2S9ARmFZ0DBvdhA9lL2nywcnKMf27PEJcKMXzXc10qaHsJw== dependencies: "@react-types/shared" "^3.23.1" -"@react-types/tooltip@^3.4.9", "@react-types/tooltip@3.4.9": +"@react-types/tooltip@3.4.9", "@react-types/tooltip@^3.4.9": version "3.4.9" resolved "https://registry.npmjs.org/@react-types/tooltip/-/tooltip-3.4.9.tgz" integrity sha512-wZ+uF1+Zc43qG+cOJzioBmLUNjRa7ApdcT0LI1VvaYvH5GdfjzUJOorLX9V/vAci0XMJ50UZ+qsh79aUlw2yqg== @@ -2531,7 +2539,7 @@ resolved "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz" integrity sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ== -"@swc/helpers@^0.5.0", "@swc/helpers@0.5.5": +"@swc/helpers@0.5.5", "@swc/helpers@^0.5.0": version "0.5.5" resolved "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.5.tgz" integrity sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A== @@ -4037,7 +4045,7 @@ dependencies: "@types/react" "*" -"@types/react@*", "@types/react@^16.8.0 || ^17.0.0 || ^18.0.0", "@types/react@^16.9.0 || ^17.0.0 || ^18.0.0": +"@types/react@*": version "18.3.11" resolved "https://registry.npmjs.org/@types/react/-/react-18.3.11.tgz" integrity sha512-r6QZ069rFTjrEYgFdOck1gK7FLVsgJE7tTz0pQBczlBNUhBNk0MQH4UbnFSwjpQLMkLzgqvBBa+qGpLje16eTQ== @@ -4058,6 +4066,11 @@ abab@^2.0.5, abab@^2.0.6: resolved "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz" integrity sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA== +abbrev@1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== + abort-controller@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz" @@ -4108,13 +4121,6 @@ ag-grid-react@^32.0.2: ag-grid-community "32.1.0" prop-types "^15.8.1" -agent-base@^7.0.2, agent-base@^7.1.0: - version "7.1.1" - resolved "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz" - integrity sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA== - dependencies: - debug "^4.3.4" - agent-base@6: version "6.0.2" resolved "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz" @@ -4122,6 +4128,13 @@ agent-base@6: dependencies: debug "4" +agent-base@^7.0.2, agent-base@^7.1.0: + version "7.1.1" + resolved "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz" + integrity sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA== + dependencies: + debug "^4.3.4" + ansi-regex@^5.0.1: version "5.0.1" resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz" @@ -4164,6 +4177,19 @@ anymatch@~3.1.2: normalize-path "^3.0.0" picomatch "^2.0.4" +"aproba@^1.0.3 || ^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc" + integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ== + +are-we-there-yet@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz#372e0e7bd279d8e94c653aaa1f67200884bf3e1c" + integrity sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw== + dependencies: + delegates "^1.0.0" + readable-stream "^3.6.0" + arg@^5.0.2: version "5.0.2" resolved "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz" @@ -4231,6 +4257,14 @@ body-scroll-lock@^3.1.5: resolved "https://registry.npmjs.org/body-scroll-lock/-/body-scroll-lock-3.1.5.tgz" integrity sha512-Yi1Xaml0EvNA0OYWxXiYNqY24AfWkbA6w5vxE7GWxtKfzIbZM+Qw+aSmkgsbWzbHiy/RCSkUZBplVxTA+E4jJg== +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + brace-expansion@^2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz" @@ -4285,6 +4319,15 @@ caniuse-lite@^1.0.30001579: resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001634.tgz" integrity sha512-fbBYXQ9q3+yp1q1gBk86tOFs4pyn/yxFm5ZNP18OXJDfA3txImOY9PhfxVggZ4vRHDqoU8NrKU81eN0OtzOgRA== +canvas@^2.8.0: + version "2.11.2" + resolved "https://registry.yarnpkg.com/canvas/-/canvas-2.11.2.tgz#553d87b1e0228c7ac0fc72887c3adbac4abbd860" + integrity sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw== + dependencies: + "@mapbox/node-pre-gyp" "^1.0.0" + nan "^2.17.0" + simple-get "^3.0.3" + chalk@^2.4.2: version "2.4.2" resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" @@ -4294,7 +4337,7 @@ chalk@^2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chokidar@^3.5.3, "chokidar@>=3.0.0 <4.0.0": +"chokidar@>=3.0.0 <4.0.0", chokidar@^3.5.3: version "3.6.0" resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz" integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== @@ -4309,22 +4352,22 @@ chokidar@^3.5.3, "chokidar@>=3.0.0 <4.0.0": optionalDependencies: fsevents "~2.3.2" +chownr@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" + integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== + classnames@^2.3.1: version "2.5.1" resolved "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz" integrity sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow== -client-only@^0.0.1, client-only@0.0.1: +client-only@0.0.1, client-only@^0.0.1: version "0.0.1" resolved "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz" integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA== -clsx@^1.1.1: - version "1.2.1" - resolved "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz" - integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg== - -clsx@^1.2.1: +clsx@^1.1.1, clsx@^1.2.1: version "1.2.1" resolved "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz" integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg== @@ -4348,16 +4391,16 @@ color-convert@^2.0.1: dependencies: color-name "~1.1.4" -color-name@^1.0.0, color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - color-name@1.1.3: version "1.1.3" resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== +color-name@^1.0.0, color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + color-string@^1.9.0: version "1.9.1" resolved "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz" @@ -4366,6 +4409,16 @@ color-string@^1.9.0: color-name "^1.0.0" simple-swizzle "^0.2.2" +color-support@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" + integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== + +color2k@^2.0.2: + version "2.0.3" + resolved "https://registry.npmjs.org/color2k/-/color2k-2.0.3.tgz" + integrity sha512-zW190nQTIoXcGCaU08DvVNFTmQhUpnJfVuAKfWqUQkflXKpaDdpaYoM0iluLS9lgJNHyBF58KKA2FBEwkD7wog== + color@^4.2.3: version "4.2.3" resolved "https://registry.npmjs.org/color/-/color-4.2.3.tgz" @@ -4374,11 +4427,6 @@ color@^4.2.3: color-convert "^2.0.1" color-string "^1.9.0" -color2k@^2.0.2: - version "2.0.3" - resolved "https://registry.npmjs.org/color2k/-/color2k-2.0.3.tgz" - integrity sha512-zW190nQTIoXcGCaU08DvVNFTmQhUpnJfVuAKfWqUQkflXKpaDdpaYoM0iluLS9lgJNHyBF58KKA2FBEwkD7wog== - combined-stream@^1.0.8: version "1.0.8" resolved "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz" @@ -4386,6 +4434,11 @@ combined-stream@^1.0.8: dependencies: delayed-stream "~1.0.0" +commander@2: + version "2.20.3" + resolved "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + commander@^11.0.0: version "11.1.0" resolved "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz" @@ -4396,11 +4449,6 @@ commander@^4.0.0: resolved "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz" integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== -commander@2: - version "2.20.3" - resolved "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz" - integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== - complex.js@^2.1.1: version "2.1.1" resolved "https://registry.npmjs.org/complex.js/-/complex.js-2.1.1.tgz" @@ -4411,6 +4459,11 @@ compute-scroll-into-view@^3.0.2: resolved "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-3.1.0.tgz" integrity sha512-rj8l8pD4bJ1nx+dAkMhV1xB5RuZEyVysfxJqB1pRchh1KVvwOv9b7CGB8ZfjTImVv2oF+sYMUkMZq6Na5Ftmbg== +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + concaveman@^1.2.1: version "1.2.1" resolved "https://registry.npmjs.org/concaveman/-/concaveman-1.2.1.tgz" @@ -4421,6 +4474,11 @@ concaveman@^1.2.1: robust-predicates "^2.0.4" tinyqueue "^2.0.3" +console-control-strings@^1.0.0, console-control-strings@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ== + convert-source-map@^1.5.0: version "1.9.0" resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz" @@ -4521,6 +4579,13 @@ dayjs@^1.11.13: resolved "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz" integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg== +debug@4, debug@^4.3.3, debug@^4.3.4: + version "4.3.5" + resolved "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz" + integrity sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg== + dependencies: + ms "2.1.2" + debug@^4.3.1: version "4.3.7" resolved "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz" @@ -4528,18 +4593,18 @@ debug@^4.3.1: dependencies: ms "^2.1.3" -debug@^4.3.3, debug@^4.3.4, debug@4: - version "4.3.5" - resolved "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz" - integrity sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg== - dependencies: - ms "2.1.2" - decimal.js@^10.3.1, decimal.js@^10.4.3: version "10.4.3" resolved "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz" integrity sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA== +decompress-response@^4.2.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-4.2.1.tgz#414023cc7a302da25ce2ec82d0d5238ccafd8986" + integrity sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw== + dependencies: + mimic-response "^2.0.0" + deepmerge@4.3.1: version "4.3.1" resolved "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz" @@ -4555,6 +4620,16 @@ delayed-stream@~1.0.0: resolved "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz" integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ== + +detect-libc@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.3.tgz#f0cd503b40f9939b894697d19ad50895e30cf700" + integrity sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw== + detect-node-es@^1.1.0: version "1.1.0" resolved "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz" @@ -4745,13 +4820,25 @@ fraction.js@^4.3.7: resolved "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz" integrity sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew== -framer-motion@^11.2.13, framer-motion@>=10.17.0: +framer-motion@^11.2.13: version "11.3.21" resolved "https://registry.npmjs.org/framer-motion/-/framer-motion-11.3.21.tgz" integrity sha512-D+hfIsvzV8eL/iycld4K+tKlg2Q2LdwnrcBEohtGw3cG1AIuNYATbT5RUqIM1ndsAk+EfGhoSGf0UaiFodc5Tw== dependencies: tslib "^2.4.0" +fs-minipass@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" + integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== + dependencies: + minipass "^3.0.0" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + fs@^0.0.1-security: version "0.0.1-security" resolved "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz" @@ -4767,6 +4854,21 @@ function-bind@^1.1.2: resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz" integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== +gauge@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-3.0.2.tgz#03bf4441c044383908bcfa0656ad91803259b395" + integrity sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q== + dependencies: + aproba "^1.0.3 || ^2.0.0" + color-support "^1.1.2" + console-control-strings "^1.0.0" + has-unicode "^2.0.1" + object-assign "^4.1.1" + signal-exit "^3.0.0" + string-width "^4.2.3" + strip-ansi "^6.0.1" + wide-align "^1.1.2" + geojson-equality-ts@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/geojson-equality-ts/-/geojson-equality-ts-1.0.2.tgz" @@ -4811,6 +4913,18 @@ glob@^10.3.10: minipass "^7.1.2" path-scurry "^1.11.1" +glob@^7.1.3: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + globals@^11.1.0: version "11.12.0" resolved "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz" @@ -4831,6 +4945,11 @@ has-flag@^3.0.0: resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== +has-unicode@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + integrity sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ== + hasown@^2.0.0: version "2.0.2" resolved "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz" @@ -4885,7 +5004,7 @@ https-proxy-agent@^7.0.0: agent-base "^7.0.2" debug "4" -iconv-lite@^0.6.3, iconv-lite@0.6.3: +iconv-lite@0.6.3, iconv-lite@^0.6.3: version "0.6.3" resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz" integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== @@ -4910,9 +5029,17 @@ import-fresh@^3.2.1: parent-module "^1.0.0" resolve-from "^4.0.0" -inherits@^2.0.4: +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@^2.0.3, inherits@^2.0.4: version "2.0.4" - resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== international-types@^0.8.1: @@ -5243,6 +5370,13 @@ lru-cache@^10.2.0: resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz" integrity sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ== +make-dir@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== + dependencies: + semver "^6.0.0" + marchingsquares@^1.3.3: version "1.3.3" resolved "https://registry.npmjs.org/marchingsquares/-/marchingsquares-1.3.3.tgz" @@ -5293,6 +5427,18 @@ mime-types@^2.1.12: dependencies: mime-db "1.52.0" +mimic-response@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-2.1.0.tgz#d13763d35f613d09ec37ebb30bac0469c0ee8f43" + integrity sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA== + +minimatch@^3.1.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + minimatch@^9.0.4: version "9.0.4" resolved "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz" @@ -5300,17 +5446,37 @@ minimatch@^9.0.4: dependencies: brace-expansion "^2.0.1" -"minipass@^5.0.0 || ^6.0.2 || ^7.0.0": +minipass@^3.0.0: + version "3.3.6" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.6.tgz#7bba384db3a1520d18c9c0e5251c3444e95dd94a" + integrity sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw== + dependencies: + yallist "^4.0.0" + +minipass@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-5.0.0.tgz#3e9788ffb90b694a5d0ec94479a45b5d8738133d" + integrity sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ== + +"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.1.2: version "7.1.2" resolved "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz" integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== -minipass@^7.1.2: - version "7.1.2" - resolved "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz" - integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== +minizlib@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" + integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== + dependencies: + minipass "^3.0.0" + yallist "^4.0.0" -ms@^2.1.1, ms@2.1.2: +mkdirp@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + +ms@2.1.2, ms@^2.1.1: version "2.1.2" resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== @@ -5341,6 +5507,11 @@ mz@^2.7.0: object-assign "^4.0.1" thenify-all "^1.0.0" +nan@^2.17.0: + version "2.22.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.22.0.tgz#31bc433fc33213c97bad36404bb68063de604de3" + integrity sha512-nbajikzWTMwsW+eSsNm3QwlOs7het9gGJU5dDZzRTQGk03vyBOauxgI4VakDzE0PtsGTmXPsXTbbjVhRwR5mpw== + nanoid@^3.3.6, nanoid@^3.3.7: version "3.3.7" resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz" @@ -5383,11 +5554,35 @@ next@14.2.3: "@next/swc-win32-ia32-msvc" "14.2.3" "@next/swc-win32-x64-msvc" "14.2.3" +node-fetch@^2.6.7: + version "2.7.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== + dependencies: + whatwg-url "^5.0.0" + +nopt@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-5.0.0.tgz#530942bb58a512fccafe53fe210f13a25355dc88" + integrity sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ== + dependencies: + abbrev "1" + normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== +npmlog@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-5.0.1.tgz#f06678e80e29419ad67ab964e0fa69959c1eb8b0" + integrity sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw== + dependencies: + are-we-there-yet "^2.0.0" + console-control-strings "^1.1.0" + gauge "^3.0.0" + set-blocking "^2.0.0" + nwsapi@^2.2.0: version "2.2.10" resolved "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.10.tgz" @@ -5403,6 +5598,13 @@ object-hash@^3.0.0: resolved "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz" integrity sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw== +once@^1.3.0, once@^1.3.1: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + open@^8.0.0: version "8.4.2" resolved "https://registry.npmjs.org/open/-/open-8.4.2.tgz" @@ -5434,6 +5636,11 @@ parse5@6.0.1: resolved "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz" integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + path-key@^3.1.0: version "3.1.1" resolved "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz" @@ -5539,15 +5746,6 @@ postcss-value-parser@^4.0.0: resolved "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz" integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== -postcss@^8, postcss@^8.0.0, postcss@^8.2.14, postcss@^8.4.21, postcss@^8.4.23, postcss@>=8.0.9: - version "8.4.38" - resolved "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz" - integrity sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A== - dependencies: - nanoid "^3.3.7" - picocolors "^1.0.0" - source-map-js "^1.2.0" - postcss@8.4.31: version "8.4.31" resolved "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz" @@ -5557,6 +5755,15 @@ postcss@8.4.31: picocolors "^1.0.0" source-map-js "^1.0.2" +postcss@^8, postcss@^8.4.23: + version "8.4.38" + resolved "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz" + integrity sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A== + dependencies: + nanoid "^3.3.7" + picocolors "^1.0.0" + source-map-js "^1.2.0" + prettier@^3.3.3: version "3.3.3" resolved "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz" @@ -5646,7 +5853,7 @@ react-datepicker@^7.3.0: prop-types "^15.7.2" react-onclickoutside "^6.13.0" -"react-dom@^15.5.x || ^16.x || ^17.x || ^18.x", "react-dom@^16.3.0 || ^17.0.0 || ^18.0.0", "react-dom@^16.8.0 || ^17 || ^18", "react-dom@^16.8.0 || ^17.0.0 || ^18.0.0", "react-dom@^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", "react-dom@^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0", "react-dom@^16.9.0 || ^17 || ^18", react-dom@^18, react-dom@^18.0.0, react-dom@^18.2.0, "react-dom@>= 16.3.0", react-dom@>=16.6.0, react-dom@>=16.8.0, react-dom@>=18: +react-dom@^18: version "18.3.1" resolved "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz" integrity sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw== @@ -5758,7 +5965,7 @@ react-transition-group@^4.3.0: loose-envify "^1.4.0" prop-types "^15.6.2" -react@*, "react@^15.5.x || ^16.x || ^17.x || ^18.x", "react@^16.3.0 || ^17.0.0 || ^18.0.0", "react@^16.8 || ^17 || ^18", "react@^16.8.0 || ^17 || ^18", "react@^16.8.0 || ^17 || ^18 || ^19", "react@^16.8.0 || ^17.0.0 || ^18.0.0", "react@^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", "react@^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0", "react@^16.9.0 || ^17 || ^18", react@^18, react@^18.0.0, react@^18.2.0, react@^18.3.1, "react@>= 16.3.0", "react@>= 16.8.0 || 17.x.x || ^18.0.0-0", react@>=16.13.1, react@>=16.6.0, react@>=16.8, react@>=16.8.0, react@>=18: +react@^18: version "18.3.1" resolved "https://registry.npmjs.org/react/-/react-18.3.1.tgz" integrity sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ== @@ -5772,6 +5979,15 @@ read-cache@^1.0.0: dependencies: pify "^2.3.0" +readable-stream@^3.6.0: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + readable-stream@^4.2.0: version "4.5.2" resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz" @@ -5831,6 +6047,13 @@ rfdc@^1.3.0: resolved "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz" integrity sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA== +rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + robust-predicates@^2.0.4: version "2.0.4" resolved "https://registry.npmjs.org/robust-predicates/-/robust-predicates-2.0.4.tgz" @@ -5863,7 +6086,7 @@ safe-buffer@~5.1.1: resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -sass@^1.3.0, sass@^1.77.8: +sass@^1.77.8: version "1.77.8" resolved "https://registry.npmjs.org/sass/-/sass-1.77.8.tgz" integrity sha512-4UHg6prsrycW20fqLGPShtEvo/WyHRVRHwOP4DzkUrObWoWI05QBSfzU71TVB7PFaL104TwNaHpjlWXAZbQiNQ== @@ -5898,6 +6121,16 @@ seedrandom@^3.0.5: resolved "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz" integrity sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg== +semver@^6.0.0: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +semver@^7.3.5: + version "7.6.3" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" + integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== + semver@^7.5.4: version "7.6.2" resolved "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz" @@ -5908,6 +6141,11 @@ server-only@^0.0.1: resolved "https://registry.npmjs.org/server-only/-/server-only-0.0.1.tgz" integrity sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA== +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== + shebang-command@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz" @@ -5920,11 +6158,30 @@ shebang-regex@^3.0.0: resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== +signal-exit@^3.0.0: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + signal-exit@^4.0.1: version "4.1.0" resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz" integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== +simple-concat@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f" + integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q== + +simple-get@^3.0.3: + version "3.1.1" + resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-3.1.1.tgz#cc7ba77cfbe761036fbfce3d021af25fc5584d55" + integrity sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA== + dependencies: + decompress-response "^4.2.0" + once "^1.3.1" + simple-concat "^1.0.0" + simple-swizzle@^0.2.2: version "0.2.2" resolved "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz" @@ -5937,7 +6194,7 @@ skmeans@0.9.7: resolved "https://registry.npmjs.org/skmeans/-/skmeans-0.9.7.tgz" integrity sha512-hNj1/oZ7ygsfmPZ7ZfN5MUBRoGg1gtpnImuJBgLO0ljQ67DtJuiQaiYdS4lUA6s0KCwnPhGivtC/WRwIZLkHyg== -source-map-js@^1.0.2, source-map-js@^1.2.0, "source-map-js@>=0.6.2 <2.0.0": +"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.2, source-map-js@^1.2.0: version "1.2.0" resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz" integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg== @@ -5972,13 +6229,6 @@ streamsearch@^1.1.0: resolved "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz" integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg== -string_decoder@^1.3.0: - version "1.3.0" - resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz" - integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== - dependencies: - safe-buffer "~5.2.0" - "string-width-cjs@npm:string-width@^4.2.0": version "4.2.3" resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" @@ -5988,16 +6238,16 @@ string_decoder@^1.3.0: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" -string-width@^4.1.0: +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.3: version "4.2.3" - resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== dependencies: emoji-regex "^8.0.0" is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" -string-width@^5.0.1: +string-width@^5.0.1, string-width@^5.1.2: version "5.1.2" resolved "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz" integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== @@ -6006,14 +6256,12 @@ string-width@^5.0.1: emoji-regex "^9.2.2" strip-ansi "^7.0.1" -string-width@^5.1.2: - version "5.1.2" - resolved "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz" - integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== +string_decoder@^1.1.1, string_decoder@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== dependencies: - eastasianwidth "^0.2.0" - emoji-regex "^9.2.2" - strip-ansi "^7.0.1" + safe-buffer "~5.2.0" "strip-ansi-cjs@npm:strip-ansi@^6.0.1": version "6.0.1" @@ -6085,7 +6333,7 @@ sweetalert2-react-content@^5.0.7: resolved "https://registry.npmjs.org/sweetalert2-react-content/-/sweetalert2-react-content-5.0.7.tgz" integrity sha512-8Fk82Mpk45lFXpJWKIFF/lq8k/dJKDDQGFcuqVosaL/qRdViyAs5+u37LoTGfnOIvf+rfQB3PAXcp1XLLn+0ew== -sweetalert2@^11.0.0, sweetalert2@^11.14.1: +sweetalert2@^11.14.1: version "11.14.1" resolved "https://registry.npmjs.org/sweetalert2/-/sweetalert2-11.14.1.tgz" integrity sha512-xadhfcA4STGMh8nC5zHFFWURhRpWc4zyI3GdMDFH/m3hGWZeQQNWhX9xcG4lI9gZYsi/IlazKbwvvje3juL3Xg== @@ -6112,7 +6360,7 @@ tailwind-variants@^0.1.20: dependencies: tailwind-merge "^1.14.0" -tailwindcss@*, tailwindcss@^3.4.1, tailwindcss@>=3.4.0: +tailwindcss@^3.4.1: version "3.4.4" resolved "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.4.tgz" integrity sha512-ZoyXOdJjISB7/BcLTR6SEsLgKtDStYyYZVLsUtWChO4Ps20CBad7lfJKVDiejocV4ME1hLmyY0WJE3hSDcmQ2A== @@ -6140,6 +6388,18 @@ tailwindcss@*, tailwindcss@^3.4.1, tailwindcss@>=3.4.0: resolve "^1.22.2" sucrase "^3.32.0" +tar@^6.1.11: + version "6.2.1" + resolved "https://registry.yarnpkg.com/tar/-/tar-6.2.1.tgz#717549c541bc3c2af15751bea94b1dd068d4b03a" + integrity sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A== + dependencies: + chownr "^2.0.0" + fs-minipass "^2.0.0" + minipass "^5.0.0" + minizlib "^2.1.1" + mkdirp "^1.0.3" + yallist "^4.0.0" + tarn@^3.0.2: version "3.0.2" resolved "https://registry.npmjs.org/tarn/-/tarn-3.0.2.tgz" @@ -6228,6 +6488,11 @@ tr46@^3.0.0: dependencies: punycode "^2.1.1" +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== + ts-interface-checker@^0.1.9: version "0.1.13" resolved "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz" @@ -6298,9 +6563,9 @@ use-sidecar@^1.1.2: detect-node-es "^1.1.0" tslib "^2.0.0" -util-deprecate@^1.0.2: +util-deprecate@^1.0.1, util-deprecate@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== uuid@^10.0.0: @@ -6327,6 +6592,11 @@ w3c-xmlserializer@^3.0.0: dependencies: xml-name-validator "^4.0.0" +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== + webidl-conversions@^7.0.0: version "7.0.0" resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz" @@ -6360,6 +6630,14 @@ whatwg-url@^11.0.0: tr46 "^3.0.0" webidl-conversions "^7.0.0" +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + which@^2.0.1: version "2.0.2" resolved "https://registry.npmjs.org/which/-/which-2.0.2.tgz" @@ -6367,6 +6645,13 @@ which@^2.0.1: dependencies: isexe "^2.0.0" +wide-align@^1.1.2: + version "1.1.5" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3" + integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg== + dependencies: + string-width "^1.0.2 || 2 || 3 || 4" + "wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" @@ -6385,6 +6670,11 @@ wrap-ansi@^8.1.0: string-width "^5.0.1" strip-ansi "^7.0.1" +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + ws@^8.2.3: version "8.17.1" resolved "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz" @@ -6400,6 +6690,11 @@ xmlchars@^2.2.0: resolved "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz" integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + yaml@^1.10.0: version "1.10.2" resolved "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz" From 0b3390546f97006a49580c2e0a8bd8556890bc46 Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Fri, 1 Nov 2024 17:43:15 +0900 Subject: [PATCH 02/51] =?UTF-8?q?fix:=20=EB=8F=84=EB=A9=B4=EC=9D=84=20?= =?UTF-8?q?=EC=9D=B4=EB=AF=B8=EC=A7=80=EB=A1=9C=20=EC=BB=A8=EB=B2=84?= =?UTF-8?q?=ED=8C=85=20=ED=9B=84=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EC=97=85?= =?UTF-8?q?=EB=A1=9C=EB=93=9C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../placementShape/PlacementShapeSetting.jsx | 4 +-- src/hooks/common/useRefFiles.js | 30 ++++++++++++++++++- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx b/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx index 539dbdf1..2052bff9 100644 --- a/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx +++ b/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx @@ -19,7 +19,7 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set const [canvasSetting, setCanvasSetting] = useRecoilState(canvasSettingState) const { closePopup } = usePopup() const [basicSetting, setBasicSettings] = useRecoilState(basicSettingState) - const { refImage, setRefImage } = useRefFiles() + const { refImage, setRefImage, handleRefFile } = useRefFiles() const { getMessage } = useMessage() const { get, post } = useAxios() @@ -490,7 +490,7 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set {getMessage('common.input.file.load')} - setRefImage(e.target.files[0])} /> + handleRefFile(e.target.files[0])} />
diff --git a/src/hooks/common/useRefFiles.js b/src/hooks/common/useRefFiles.js index 8cb046d5..c241b1e0 100644 --- a/src/hooks/common/useRefFiles.js +++ b/src/hooks/common/useRefFiles.js @@ -1,11 +1,39 @@ import { useState } from 'react' +import { convertDwgToPng } from '@/lib/cadAction' +import { useSwal } from '@/hooks/useSwal' export default function useRefFiles() { - const [refImage, setRefImage] = useState(null) const converterUrl = process.env.NEXT_PUBLIC_CONVERTER_API_URL + const [refImage, setRefImage] = useState(null) + + const { swalFire } = useSwal() + + const handleRefFile = (file) => { + setRefImage(file) + console.log('🚀 ~ handleRefFile ~ file:', file) + file.name.split('.').pop() === 'dwg' ? handleUploadRefFile(file) : () => {} + console.log("🚀 ~ handleRefFile ~ file.name.split('.').pop():", file.name.split('.').pop()) + // handleUploadRefFile(file) + } + + // RefFile이 캐드 도면 파일일 경우 변환하여 이미지로 저장 + const handleUploadRefFile = async (file) => { + const formData = new FormData() + formData.append('file', file) + + await promisePost({ url: converterUrl, data: formData }) + .then((res) => { + convertDwgToPng(res.data.Files[0].FileName, res.data.Files[0].FileData) + swalFire({ text: '파일 변환 성공' }) + }) + .catch((err) => { + swalFire({ text: '파일 변환 실패', icon: 'error' }) + }) + } return { refImage, setRefImage, + handleRefFile, } } From 4b56a0a5f821c70b8667092c6c1ea6dafe040d6a Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Fri, 1 Nov 2024 13:21:55 +0900 Subject: [PATCH 03/51] feat: Add floor-plan image load feature --- .../placementShape/PlacementShapeSetting.jsx | 9 +- src/hooks/common/useRefFiles.js | 11 + yarn.lock | 595 +++++++++++++----- 3 files changed, 461 insertions(+), 154 deletions(-) create mode 100644 src/hooks/common/useRefFiles.js diff --git a/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx b/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx index 99b72eb4..539dbdf1 100644 --- a/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx +++ b/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx @@ -9,6 +9,7 @@ import { useAxios } from '@/hooks/useAxios' import { useSwal } from '@/hooks/useSwal' import { usePopup } from '@/hooks/usePopup' import { basicSettingState } from '@/store/settingAtom' +import useRefFiles from '@/hooks/common/useRefFiles' export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, setShowPlaceShapeModal }) { const [objectNo, setObjectNo] = useState('test123241008001') // 후에 삭제 필요 @@ -18,7 +19,7 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set const [canvasSetting, setCanvasSetting] = useRecoilState(canvasSettingState) const { closePopup } = usePopup() const [basicSetting, setBasicSettings] = useRecoilState(basicSettingState) - const [image, setImage] = useState(null) + const { refImage, setRefImage } = useRefFiles() const { getMessage } = useMessage() const { get, post } = useAxios() @@ -489,11 +490,11 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set {getMessage('common.input.file.load')} - setImage(e.target.files[0])} /> + setRefImage(e.target.files[0])} />
- - {image && } + + {refImage && }
diff --git a/src/hooks/common/useRefFiles.js b/src/hooks/common/useRefFiles.js new file mode 100644 index 00000000..8cb046d5 --- /dev/null +++ b/src/hooks/common/useRefFiles.js @@ -0,0 +1,11 @@ +import { useState } from 'react' + +export default function useRefFiles() { + const [refImage, setRefImage] = useState(null) + const converterUrl = process.env.NEXT_PUBLIC_CONVERTER_API_URL + + return { + refImage, + setRefImage, + } +} diff --git a/yarn.lock b/yarn.lock index f2bcf8b4..a167fa9d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -223,14 +223,7 @@ dependencies: regenerator-runtime "^0.14.0" -"@babel/runtime@^7.20.13": - version "7.25.0" - resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.0.tgz" - integrity sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw== - dependencies: - regenerator-runtime "^0.14.0" - -"@babel/runtime@^7.24.8": +"@babel/runtime@^7.20.13", "@babel/runtime@^7.24.8": version "7.25.0" resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.0.tgz" integrity sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw== @@ -534,6 +527,21 @@ resolved "https://registry.npmjs.org/@js-joda/core/-/core-5.6.3.tgz" integrity sha512-T1rRxzdqkEXcou0ZprN1q9yDRlvzCPLqmlNt5IIsGBzoEVgLCCYrKEwc84+TvsXuAc95VAZwtWD2zVsKPY4bcA== +"@mapbox/node-pre-gyp@^1.0.0": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz#417db42b7f5323d79e93b34a6d7a2a12c0df43fa" + integrity sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ== + dependencies: + detect-libc "^2.0.0" + https-proxy-agent "^5.0.0" + make-dir "^3.1.0" + node-fetch "^2.6.7" + nopt "^5.0.0" + npmlog "^5.0.1" + rimraf "^3.0.2" + semver "^7.3.5" + tar "^6.1.11" + "@next/env@14.2.3": version "14.2.3" resolved "https://registry.npmjs.org/@next/env/-/env-14.2.3.tgz" @@ -1238,7 +1246,7 @@ "@react-types/shared" "3.23.1" clsx "^1.2.1" -"@nextui-org/system@>=2.0.0", "@nextui-org/system@>=2.1.0", "@nextui-org/system@2.2.5": +"@nextui-org/system@2.2.5": version "2.2.5" resolved "https://registry.npmjs.org/@nextui-org/system/-/system-2.2.5.tgz" integrity sha512-nrX6768aiyWtpxX3OTFBIVWR+v9nlMsC3KaBinNfek97sNm7gAfTHi7q5kylE3L5yIMpNG+DclAKpuxgDQEmvw== @@ -1291,7 +1299,7 @@ "@react-types/tabs" "3.3.7" scroll-into-view-if-needed "3.0.10" -"@nextui-org/theme@>=2.1.0", "@nextui-org/theme@>=2.2.0", "@nextui-org/theme@2.2.9": +"@nextui-org/theme@2.2.9": version "2.2.9" resolved "https://registry.npmjs.org/@nextui-org/theme/-/theme-2.2.9.tgz" integrity sha512-TN2I9sMriLaj00pXsIMlg19+UHeOdjzS2JV0u4gjL14mSbQl5BYNxgbvU3gbMqkZZQ6OpwT4RnT8RS+ks6TXCw== @@ -1512,7 +1520,7 @@ "@nodelib/fs.stat" "2.0.5" run-parallel "^1.1.9" -"@nodelib/fs.stat@^2.0.2", "@nodelib/fs.stat@2.0.5": +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": version "2.0.5" resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz" integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== @@ -1645,7 +1653,7 @@ "@react-types/shared" "^3.23.1" "@swc/helpers" "^0.5.0" -"@react-aria/focus@^3.17.1", "@react-aria/focus@3.17.1": +"@react-aria/focus@3.17.1", "@react-aria/focus@^3.17.1": version "3.17.1" resolved "https://registry.npmjs.org/@react-aria/focus/-/focus-3.17.1.tgz" integrity sha512-FLTySoSNqX++u0nWZJPPN5etXY0WBxaIe/YuL/GTEeuqUIuC/2bJSaw5hlsM6T2yjy6Y/VAxBcKSdAFUlU6njQ== @@ -1667,7 +1675,7 @@ "@swc/helpers" "^0.5.0" clsx "^2.0.0" -"@react-aria/form@^3.0.5", "@react-aria/form@3.0.5": +"@react-aria/form@3.0.5", "@react-aria/form@^3.0.5": version "3.0.5" resolved "https://registry.npmjs.org/@react-aria/form/-/form-3.0.5.tgz" integrity sha512-n290jRwrrRXO3fS82MyWR+OKN7yznVesy5Q10IclSTVYHHI3VI53xtAPr/WzNjJR1um8aLhOcDNFKwnNIUUCsQ== @@ -1697,7 +1705,7 @@ "@react-types/shared" "^3.24.1" "@swc/helpers" "^0.5.0" -"@react-aria/i18n@^3.11.1", "@react-aria/i18n@3.11.1": +"@react-aria/i18n@3.11.1", "@react-aria/i18n@^3.11.1": version "3.11.1" resolved "https://registry.npmjs.org/@react-aria/i18n/-/i18n-3.11.1.tgz" integrity sha512-vuiBHw1kZruNMYeKkTGGnmPyMnM5T+gT8bz97H1FqIq1hQ6OPzmtBZ6W6l6OIMjeHI5oJo4utTwfZl495GALFQ== @@ -1725,7 +1733,7 @@ "@react-types/shared" "^3.24.1" "@swc/helpers" "^0.5.0" -"@react-aria/interactions@^3.21.3", "@react-aria/interactions@3.21.3": +"@react-aria/interactions@3.21.3", "@react-aria/interactions@^3.21.3": version "3.21.3" resolved "https://registry.npmjs.org/@react-aria/interactions/-/interactions-3.21.3.tgz" integrity sha512-BWIuf4qCs5FreDJ9AguawLVS0lV9UU+sK4CCnbCNNmYqOWY+1+gRXCsnOM32K+oMESBxilAjdHW5n1hsMqYMpA== @@ -1745,7 +1753,7 @@ "@react-types/shared" "^3.24.1" "@swc/helpers" "^0.5.0" -"@react-aria/label@^3.7.8", "@react-aria/label@3.7.8": +"@react-aria/label@3.7.8", "@react-aria/label@^3.7.8": version "3.7.8" resolved "https://registry.npmjs.org/@react-aria/label/-/label-3.7.8.tgz" integrity sha512-MzgTm5+suPA3KX7Ug6ZBK2NX9cin/RFLsv1BdafJ6CZpmUSpWnGE/yQfYUB7csN7j31OsZrD3/P56eShYWAQfg== @@ -1754,7 +1762,7 @@ "@react-types/shared" "^3.23.1" "@swc/helpers" "^0.5.0" -"@react-aria/link@^3.7.1", "@react-aria/link@3.7.1": +"@react-aria/link@3.7.1", "@react-aria/link@^3.7.1": version "3.7.1" resolved "https://registry.npmjs.org/@react-aria/link/-/link-3.7.1.tgz" integrity sha512-a4IaV50P3fXc7DQvEIPYkJJv26JknFbRzFT5MJOMgtzuhyJoQdILEUK6XHYjcSSNCA7uLgzpojArVk5Hz3lCpw== @@ -1766,7 +1774,7 @@ "@react-types/shared" "^3.23.1" "@swc/helpers" "^0.5.0" -"@react-aria/listbox@^3.12.1", "@react-aria/listbox@3.12.1": +"@react-aria/listbox@3.12.1", "@react-aria/listbox@^3.12.1": version "3.12.1" resolved "https://registry.npmjs.org/@react-aria/listbox/-/listbox-3.12.1.tgz" integrity sha512-7JiUp0NGykbv/HgSpmTY1wqhuf/RmjFxs1HZcNaTv8A+DlzgJYc7yQqFjP3ZA/z5RvJFuuIxggIYmgIFjaRYdA== @@ -1788,7 +1796,7 @@ dependencies: "@swc/helpers" "^0.5.0" -"@react-aria/menu@^3.14.1", "@react-aria/menu@3.14.1": +"@react-aria/menu@3.14.1", "@react-aria/menu@^3.14.1": version "3.14.1" resolved "https://registry.npmjs.org/@react-aria/menu/-/menu-3.14.1.tgz" integrity sha512-BYliRb38uAzq05UOFcD5XkjA5foQoXRbcH3ZufBsc4kvh79BcP1PMW6KsXKGJ7dC/PJWUwCui6QL1kUg8PqMHA== @@ -1807,7 +1815,7 @@ "@react-types/shared" "^3.23.1" "@swc/helpers" "^0.5.0" -"@react-aria/overlays@^3.22.1", "@react-aria/overlays@3.22.1": +"@react-aria/overlays@3.22.1", "@react-aria/overlays@^3.22.1": version "3.22.1" resolved "https://registry.npmjs.org/@react-aria/overlays/-/overlays-3.22.1.tgz" integrity sha512-GHiFMWO4EQ6+j6b5QCnNoOYiyx1Gk8ZiwLzzglCI4q1NY5AG2EAmfU4Z1+Gtrf2S5Y0zHbumC7rs9GnPoGLUYg== @@ -1852,7 +1860,7 @@ "@react-types/shared" "^3.23.1" "@swc/helpers" "^0.5.0" -"@react-aria/selection@^3.18.1", "@react-aria/selection@3.18.1": +"@react-aria/selection@3.18.1", "@react-aria/selection@^3.18.1": version "3.18.1" resolved "https://registry.npmjs.org/@react-aria/selection/-/selection-3.18.1.tgz" integrity sha512-GSqN2jX6lh7v+ldqhVjAXDcrWS3N4IsKXxO6L6Ygsye86Q9q9Mq9twWDWWu5IjHD6LoVZLUBCMO+ENGbOkyqeQ== @@ -1905,7 +1913,7 @@ "@react-types/shared" "^3.24.1" "@swc/helpers" "^0.5.0" -"@react-aria/ssr@^3.9.4", "@react-aria/ssr@3.9.4": +"@react-aria/ssr@3.9.4", "@react-aria/ssr@^3.9.4": version "3.9.4" resolved "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.9.4.tgz" integrity sha512-4jmAigVq409qcJvQyuorsmBR4+9r3+JEC60wC+Y0MZV0HCtTmm8D9guYXlJMdx0SSkgj0hHAyFm/HvPNFofCoQ== @@ -1965,7 +1973,7 @@ "@react-types/tabs" "^3.3.7" "@swc/helpers" "^0.5.0" -"@react-aria/textfield@^3.14.5", "@react-aria/textfield@3.14.5": +"@react-aria/textfield@3.14.5", "@react-aria/textfield@^3.14.5": version "3.14.5" resolved "https://registry.npmjs.org/@react-aria/textfield/-/textfield-3.14.5.tgz" integrity sha512-hj7H+66BjB1iTKKaFXwSZBZg88YT+wZboEXZ0DNdQB2ytzoz/g045wBItUuNi4ZjXI3P+0AOZznVMYadWBAmiA== @@ -2006,7 +2014,7 @@ "@react-types/tooltip" "^3.4.9" "@swc/helpers" "^0.5.0" -"@react-aria/utils@^3.24.1", "@react-aria/utils@3.24.1": +"@react-aria/utils@3.24.1", "@react-aria/utils@^3.24.1": version "3.24.1" resolved "https://registry.npmjs.org/@react-aria/utils/-/utils-3.24.1.tgz" integrity sha512-O3s9qhPMd6n42x9sKeJ3lhu5V1Tlnzhu6Yk8QOvDuXf7UGuUjXf9mzfHJt1dYzID4l9Fwm8toczBzPM9t0jc8Q== @@ -2028,7 +2036,7 @@ "@swc/helpers" "^0.5.0" clsx "^2.0.0" -"@react-aria/visually-hidden@^3.8.12", "@react-aria/visually-hidden@3.8.12": +"@react-aria/visually-hidden@3.8.12", "@react-aria/visually-hidden@^3.8.12": version "3.8.12" resolved "https://registry.npmjs.org/@react-aria/visually-hidden/-/visually-hidden-3.8.12.tgz" integrity sha512-Bawm+2Cmw3Xrlr7ARzl2RLtKh0lNUdJ0eNqzWcyx4c0VHUAWtThmH5l+HRqFUGzzutFZVo89SAy40BAbd0gjVw== @@ -2038,7 +2046,7 @@ "@react-types/shared" "^3.23.1" "@swc/helpers" "^0.5.0" -"@react-stately/calendar@^3.5.1", "@react-stately/calendar@3.5.1": +"@react-stately/calendar@3.5.1", "@react-stately/calendar@^3.5.1": version "3.5.1" resolved "https://registry.npmjs.org/@react-stately/calendar/-/calendar-3.5.1.tgz" integrity sha512-7l7QhqGUJ5AzWHfvZzbTe3J4t72Ht5BmhW4hlVI7flQXtfrmYkVtl3ZdytEZkkHmWGYZRW9b4IQTQGZxhtlElA== @@ -2049,7 +2057,7 @@ "@react-types/shared" "^3.23.1" "@swc/helpers" "^0.5.0" -"@react-stately/checkbox@^3.6.5", "@react-stately/checkbox@3.6.5": +"@react-stately/checkbox@3.6.5", "@react-stately/checkbox@^3.6.5": version "3.6.5" resolved "https://registry.npmjs.org/@react-stately/checkbox/-/checkbox-3.6.5.tgz" integrity sha512-IXV3f9k+LtmfQLE+DKIN41Q5QB/YBLDCB1YVx5PEdRp52S9+EACD5683rjVm8NVRDwjMi2SP6RnFRk7fVb5Azg== @@ -2060,7 +2068,7 @@ "@react-types/shared" "^3.23.1" "@swc/helpers" "^0.5.0" -"@react-stately/collections@^3.10.7", "@react-stately/collections@3.10.7": +"@react-stately/collections@3.10.7", "@react-stately/collections@^3.10.7": version "3.10.7" resolved "https://registry.npmjs.org/@react-stately/collections/-/collections-3.10.7.tgz" integrity sha512-KRo5O2MWVL8n3aiqb+XR3vP6akmHLhLWYZEmPKjIv0ghQaEebBTrN3wiEjtd6dzllv0QqcWvDLM1LntNfJ2TsA== @@ -2076,7 +2084,7 @@ "@react-types/shared" "^3.24.1" "@swc/helpers" "^0.5.0" -"@react-stately/combobox@^3.8.4", "@react-stately/combobox@3.8.4": +"@react-stately/combobox@3.8.4", "@react-stately/combobox@^3.8.4": version "3.8.4" resolved "https://registry.npmjs.org/@react-stately/combobox/-/combobox-3.8.4.tgz" integrity sha512-iLVGvKRRz0TeJXZhZyK783hveHpYA6xovOSdzSD+WGYpiPXo1QrcrNoH3AE0Z2sHtorU+8nc0j58vh5PB+m2AA== @@ -2091,7 +2099,7 @@ "@react-types/shared" "^3.23.1" "@swc/helpers" "^0.5.0" -"@react-stately/datepicker@^3.9.4", "@react-stately/datepicker@3.9.4": +"@react-stately/datepicker@3.9.4", "@react-stately/datepicker@^3.9.4": version "3.9.4" resolved "https://registry.npmjs.org/@react-stately/datepicker/-/datepicker-3.9.4.tgz" integrity sha512-yBdX01jn6gq4NIVvHIqdjBUPo+WN8Bujc4OnPw+ZnfA4jI0eIgq04pfZ84cp1LVXW0IB0VaCu1AlQ/kvtZjfGA== @@ -2112,7 +2120,7 @@ dependencies: "@swc/helpers" "^0.5.0" -"@react-stately/form@^3.0.3", "@react-stately/form@3.0.3": +"@react-stately/form@3.0.3", "@react-stately/form@^3.0.3": version "3.0.3" resolved "https://registry.npmjs.org/@react-stately/form/-/form-3.0.3.tgz" integrity sha512-92YYBvlHEWUGUpXgIaQ48J50jU9XrxfjYIN8BTvvhBHdD63oWgm8DzQnyT/NIAMzdLnhkg7vP+fjG8LjHeyIAg== @@ -2139,7 +2147,7 @@ "@react-types/shared" "^3.24.1" "@swc/helpers" "^0.5.0" -"@react-stately/list@^3.10.5", "@react-stately/list@3.10.5": +"@react-stately/list@3.10.5", "@react-stately/list@^3.10.5": version "3.10.5" resolved "https://registry.npmjs.org/@react-stately/list/-/list-3.10.5.tgz" integrity sha512-fV9plO+6QDHiewsYIhboxcDhF17GO95xepC5ki0bKXo44gr14g/LSo/BMmsaMnV+1BuGdBunB05bO4QOIaigXA== @@ -2161,7 +2169,7 @@ "@react-types/shared" "^3.24.1" "@swc/helpers" "^0.5.0" -"@react-stately/menu@^3.7.1", "@react-stately/menu@3.7.1": +"@react-stately/menu@3.7.1", "@react-stately/menu@^3.7.1": version "3.7.1" resolved "https://registry.npmjs.org/@react-stately/menu/-/menu-3.7.1.tgz" integrity sha512-mX1w9HHzt+xal1WIT2xGrTQsoLvDwuB2R1Er1MBABs//MsJzccycatcgV/J/28m6tO5M9iuFQQvLV+i1dCtodg== @@ -2171,7 +2179,7 @@ "@react-types/shared" "^3.23.1" "@swc/helpers" "^0.5.0" -"@react-stately/overlays@^3.6.7", "@react-stately/overlays@3.6.7": +"@react-stately/overlays@3.6.7", "@react-stately/overlays@^3.6.7": version "3.6.7" resolved "https://registry.npmjs.org/@react-stately/overlays/-/overlays-3.6.7.tgz" integrity sha512-6zp8v/iNUm6YQap0loaFx6PlvN8C0DgWHNlrlzMtMmNuvjhjR0wYXVaTfNoUZBWj25tlDM81ukXOjpRXg9rLrw== @@ -2189,7 +2197,7 @@ "@react-types/overlays" "^3.8.9" "@swc/helpers" "^0.5.0" -"@react-stately/radio@^3.10.4", "@react-stately/radio@3.10.4": +"@react-stately/radio@3.10.4", "@react-stately/radio@^3.10.4": version "3.10.4" resolved "https://registry.npmjs.org/@react-stately/radio/-/radio-3.10.4.tgz" integrity sha512-kCIc7tAl4L7Hu4Wt9l2jaa+MzYmAJm0qmC8G8yPMbExpWbLRu6J8Un80GZu+JxvzgDlqDyrVvyv9zFifwH/NkQ== @@ -2222,7 +2230,7 @@ "@react-types/shared" "^3.24.1" "@swc/helpers" "^0.5.0" -"@react-stately/slider@^3.5.4", "@react-stately/slider@3.5.4": +"@react-stately/slider@3.5.4", "@react-stately/slider@^3.5.4": version "3.5.4" resolved "https://registry.npmjs.org/@react-stately/slider/-/slider-3.5.4.tgz" integrity sha512-Jsf7K17dr93lkNKL9ij8HUcoM1sPbq8TvmibD6DhrK9If2lje+OOL8y4n4qreUnfMT56HCAeS9wCO3fg3eMyrw== @@ -2232,7 +2240,7 @@ "@react-types/slider" "^3.7.3" "@swc/helpers" "^0.5.0" -"@react-stately/table@^3.11.8", "@react-stately/table@3.11.8": +"@react-stately/table@3.11.8", "@react-stately/table@^3.11.8": version "3.11.8" resolved "https://registry.npmjs.org/@react-stately/table/-/table-3.11.8.tgz" integrity sha512-EdyRW3lT1/kAVDp5FkEIi1BQ7tvmD2YgniGdLuW/l9LADo0T+oxZqruv60qpUS6sQap+59Riaxl91ClDxrJnpg== @@ -2247,7 +2255,7 @@ "@react-types/table" "^3.9.5" "@swc/helpers" "^0.5.0" -"@react-stately/tabs@^3.6.6", "@react-stately/tabs@3.6.6": +"@react-stately/tabs@3.6.6", "@react-stately/tabs@^3.6.6": version "3.6.6" resolved "https://registry.npmjs.org/@react-stately/tabs/-/tabs-3.6.6.tgz" integrity sha512-sOLxorH2uqjAA+v1ppkMCc2YyjgqvSGeBDgtR/lyPSDd4CVMoTExszROX2dqG0c8il9RQvzFuufUtQWMY6PgSA== @@ -2257,7 +2265,7 @@ "@react-types/tabs" "^3.3.7" "@swc/helpers" "^0.5.0" -"@react-stately/toggle@^3.7.4", "@react-stately/toggle@3.7.4": +"@react-stately/toggle@3.7.4", "@react-stately/toggle@^3.7.4": version "3.7.4" resolved "https://registry.npmjs.org/@react-stately/toggle/-/toggle-3.7.4.tgz" integrity sha512-CoYFe9WrhLkDP4HGDpJYQKwfiYCRBAeoBQHv+JWl5eyK61S8xSwoHsveYuEZ3bowx71zyCnNAqWRrmNOxJ4CKA== @@ -2275,7 +2283,7 @@ "@react-types/checkbox" "^3.8.3" "@swc/helpers" "^0.5.0" -"@react-stately/tooltip@^3.4.9", "@react-stately/tooltip@3.4.9": +"@react-stately/tooltip@3.4.9", "@react-stately/tooltip@^3.4.9": version "3.4.9" resolved "https://registry.npmjs.org/@react-stately/tooltip/-/tooltip-3.4.9.tgz" integrity sha512-P7CDJsdoKarz32qFwf3VNS01lyC+63gXpDZG31pUu+EO5BeQd4WKN/AH1Beuswpr4GWzxzFc1aXQgERFGVzraA== @@ -2284,7 +2292,7 @@ "@react-types/tooltip" "^3.4.9" "@swc/helpers" "^0.5.0" -"@react-stately/tree@^3.8.1", "@react-stately/tree@3.8.1": +"@react-stately/tree@3.8.1", "@react-stately/tree@^3.8.1": version "3.8.1" resolved "https://registry.npmjs.org/@react-stately/tree/-/tree-3.8.1.tgz" integrity sha512-LOdkkruJWch3W89h4B/bXhfr0t0t1aRfEp+IMrrwdRAl23NaPqwl5ILHs4Xu5XDHqqhg8co73pHrJwUyiTWEjw== @@ -2295,7 +2303,7 @@ "@react-types/shared" "^3.23.1" "@swc/helpers" "^0.5.0" -"@react-stately/utils@^3.10.1", "@react-stately/utils@3.10.1": +"@react-stately/utils@3.10.1", "@react-stately/utils@^3.10.1": version "3.10.1" resolved "https://registry.npmjs.org/@react-stately/utils/-/utils-3.10.1.tgz" integrity sha512-VS/EHRyicef25zDZcM/ClpzYMC5i2YGN6uegOeQawmgfGjb02yaCX0F0zR69Pod9m2Hr3wunTbtpgVXvYbZItg== @@ -2309,7 +2317,7 @@ dependencies: "@swc/helpers" "^0.5.0" -"@react-stately/virtualizer@^3.7.1", "@react-stately/virtualizer@3.7.1": +"@react-stately/virtualizer@3.7.1", "@react-stately/virtualizer@^3.7.1": version "3.7.1" resolved "https://registry.npmjs.org/@react-stately/virtualizer/-/virtualizer-3.7.1.tgz" integrity sha512-voHgE6EQ+oZaLv6u2umKxakvIKNkCQuUihqKACTjdslp7SJh4Mvs3oLBI0hf0JOh+rCcFIKDvQtFwy1fXFRYBA== @@ -2325,7 +2333,7 @@ dependencies: "@react-types/shared" "^3.23.1" -"@react-types/breadcrumbs@^3.7.5", "@react-types/breadcrumbs@3.7.5": +"@react-types/breadcrumbs@3.7.5", "@react-types/breadcrumbs@^3.7.5": version "3.7.5" resolved "https://registry.npmjs.org/@react-types/breadcrumbs/-/breadcrumbs-3.7.5.tgz" integrity sha512-lV9IDYsMiu2TgdMIjEmsOE0YWwjb3jhUNK1DCZZfq6uWuiHLgyx2EncazJBUWSjHJ4ta32j7xTuXch+8Ai6u/A== @@ -2333,7 +2341,7 @@ "@react-types/link" "^3.5.5" "@react-types/shared" "^3.23.1" -"@react-types/button@^3.9.4", "@react-types/button@3.9.4": +"@react-types/button@3.9.4", "@react-types/button@^3.9.4": version "3.9.4" resolved "https://registry.npmjs.org/@react-types/button/-/button-3.9.4.tgz" integrity sha512-raeQBJUxBp0axNF74TXB8/H50GY8Q3eV6cEKMbZFP1+Dzr09Ngv0tJBeW0ewAxAguNH5DRoMUAUGIXtSXskVdA== @@ -2347,7 +2355,7 @@ dependencies: "@react-types/shared" "^3.24.1" -"@react-types/calendar@^3.4.6", "@react-types/calendar@3.4.6": +"@react-types/calendar@3.4.6", "@react-types/calendar@^3.4.6": version "3.4.6" resolved "https://registry.npmjs.org/@react-types/calendar/-/calendar-3.4.6.tgz" integrity sha512-WSntZPwtvsIYWvBQRAPvuCn55UTJBZroTvX0vQvWykJRQnPAI20G1hMQ3dNsnAL+gLZUYxBXn66vphmjUuSYew== @@ -2355,7 +2363,7 @@ "@internationalized/date" "^3.5.4" "@react-types/shared" "^3.23.1" -"@react-types/checkbox@^3.8.1", "@react-types/checkbox@3.8.1": +"@react-types/checkbox@3.8.1", "@react-types/checkbox@^3.8.1": version "3.8.1" resolved "https://registry.npmjs.org/@react-types/checkbox/-/checkbox-3.8.1.tgz" integrity sha512-5/oVByPw4MbR/8QSdHCaalmyWC71H/QGgd4aduTJSaNi825o+v/hsN2/CH7Fq9atkLKsC8fvKD00Bj2VGaKriQ== @@ -2369,14 +2377,14 @@ dependencies: "@react-types/shared" "^3.24.1" -"@react-types/combobox@^3.11.1", "@react-types/combobox@3.11.1": +"@react-types/combobox@3.11.1", "@react-types/combobox@^3.11.1": version "3.11.1" resolved "https://registry.npmjs.org/@react-types/combobox/-/combobox-3.11.1.tgz" integrity sha512-UNc3OHt5cUt5gCTHqhQIqhaWwKCpaNciD8R7eQazmHiA9fq8ROlV+7l3gdNgdhJbTf5Bu/V5ISnN7Y1xwL3zqQ== dependencies: "@react-types/shared" "^3.23.1" -"@react-types/datepicker@^3.7.4", "@react-types/datepicker@3.7.4": +"@react-types/datepicker@3.7.4", "@react-types/datepicker@^3.7.4": version "3.7.4" resolved "https://registry.npmjs.org/@react-types/datepicker/-/datepicker-3.7.4.tgz" integrity sha512-ZfvgscvNzBJpYyVWg3nstJtA/VlWLwErwSkd1ivZYam859N30w8yH+4qoYLa6FzWLCFlrsRHyvtxlEM7lUAt5A== @@ -2394,7 +2402,7 @@ "@react-types/overlays" "^3.8.9" "@react-types/shared" "^3.24.1" -"@react-types/grid@^3.2.6", "@react-types/grid@3.2.6": +"@react-types/grid@3.2.6", "@react-types/grid@^3.2.6": version "3.2.6" resolved "https://registry.npmjs.org/@react-types/grid/-/grid-3.2.6.tgz" integrity sha512-XfHenL2jEBUYrhKiPdeM24mbLRXUn79wVzzMhrNYh24nBwhsPPpxF+gjFddT3Cy8dt6tRInfT6pMEu9nsXwaHw== @@ -2408,7 +2416,7 @@ dependencies: "@react-types/shared" "^3.24.1" -"@react-types/link@^3.5.5", "@react-types/link@3.5.5": +"@react-types/link@3.5.5", "@react-types/link@^3.5.5": version "3.5.5" resolved "https://registry.npmjs.org/@react-types/link/-/link-3.5.5.tgz" integrity sha512-G6P5WagHDR87npN7sEuC5IIgL1GsoY4WFWKO4734i2CXRYx24G9P0Su3AX4GA3qpspz8sK1AWkaCzBMmvnunfw== @@ -2422,7 +2430,7 @@ dependencies: "@react-types/shared" "^3.24.1" -"@react-types/menu@^3.9.9", "@react-types/menu@3.9.9": +"@react-types/menu@3.9.9", "@react-types/menu@^3.9.9": version "3.9.9" resolved "https://registry.npmjs.org/@react-types/menu/-/menu-3.9.9.tgz" integrity sha512-FamUaPVs1Fxr4KOMI0YcR2rYZHoN7ypGtgiEiJ11v/tEPjPPGgeKDxii0McCrdOkjheatLN1yd2jmMwYj6hTDg== @@ -2430,7 +2438,7 @@ "@react-types/overlays" "^3.8.7" "@react-types/shared" "^3.23.1" -"@react-types/overlays@^3.8.7", "@react-types/overlays@3.8.7": +"@react-types/overlays@3.8.7", "@react-types/overlays@^3.8.7": version "3.8.7" resolved "https://registry.npmjs.org/@react-types/overlays/-/overlays-3.8.7.tgz" integrity sha512-zCOYvI4at2DkhVpviIClJ7bRrLXYhSg3Z3v9xymuPH3mkiuuP/dm8mUCtkyY4UhVeUTHmrQh1bzaOP00A+SSQA== @@ -2444,20 +2452,27 @@ dependencies: "@react-types/shared" "^3.24.1" -"@react-types/progress@^3.5.4", "@react-types/progress@3.5.4": +"@react-types/progress@3.5.4", "@react-types/progress@^3.5.4": version "3.5.4" resolved "https://registry.npmjs.org/@react-types/progress/-/progress-3.5.4.tgz" integrity sha512-JNc246sTjasPyx5Dp7/s0rp3Bz4qlu4LrZTulZlxWyb53WgBNL7axc26CCi+I20rWL9+c7JjhrRxnLl/1cLN5g== dependencies: "@react-types/shared" "^3.23.1" -"@react-types/radio@^3.8.1", "@react-types/radio@3.8.1": +"@react-types/radio@3.8.1", "@react-types/radio@^3.8.1": version "3.8.1" resolved "https://registry.npmjs.org/@react-types/radio/-/radio-3.8.1.tgz" integrity sha512-bK0gio/qj1+0Ldu/3k/s9BaOZvnnRgvFtL3u5ky479+aLG5qf1CmYed3SKz8ErZ70JkpuCSrSwSCFf0t1IHovw== dependencies: "@react-types/shared" "^3.23.1" +"@react-types/select@3.9.4": + version "3.9.4" + resolved "https://registry.npmjs.org/@react-types/select/-/select-3.9.4.tgz" + integrity sha512-xI7dnOW2st91fPPcv6hdtrTdcfetYiqZuuVPZ5TRobY7Q10/Zqqe/KqtOw1zFKUj9xqNJe4Ov3xP5GSdcO60Eg== + dependencies: + "@react-types/shared" "^3.23.1" + "@react-types/select@^3.9.6": version "3.9.6" resolved "https://registry.npmjs.org/@react-types/select/-/select-3.9.6.tgz" @@ -2465,14 +2480,7 @@ dependencies: "@react-types/shared" "^3.24.1" -"@react-types/select@3.9.4": - version "3.9.4" - resolved "https://registry.npmjs.org/@react-types/select/-/select-3.9.4.tgz" - integrity sha512-xI7dnOW2st91fPPcv6hdtrTdcfetYiqZuuVPZ5TRobY7Q10/Zqqe/KqtOw1zFKUj9xqNJe4Ov3xP5GSdcO60Eg== - dependencies: - "@react-types/shared" "^3.23.1" - -"@react-types/shared@^3.23.1", "@react-types/shared@3.23.1": +"@react-types/shared@3.23.1", "@react-types/shared@^3.23.1": version "3.23.1" resolved "https://registry.npmjs.org/@react-types/shared/-/shared-3.23.1.tgz" integrity sha512-5d+3HbFDxGZjhbMBeFHRQhexMFt4pUce3okyRtUVKbbedQFUrtXSBg9VszgF2RTeQDKDkMCIQDtz5ccP/Lk1gw== @@ -2496,7 +2504,7 @@ dependencies: "@react-types/shared" "^3.24.1" -"@react-types/table@^3.9.5", "@react-types/table@3.9.5": +"@react-types/table@3.9.5", "@react-types/table@^3.9.5": version "3.9.5" resolved "https://registry.npmjs.org/@react-types/table/-/table-3.9.5.tgz" integrity sha512-fgM2j9F/UR4Anmd28CueghCgBwOZoCVyN8fjaIFPd2MN4gCwUUfANwxLav65gZk4BpwUXGoQdsW+X50L3555mg== @@ -2504,21 +2512,21 @@ "@react-types/grid" "^3.2.6" "@react-types/shared" "^3.23.1" -"@react-types/tabs@^3.3.7", "@react-types/tabs@3.3.7": +"@react-types/tabs@3.3.7", "@react-types/tabs@^3.3.7": version "3.3.7" resolved "https://registry.npmjs.org/@react-types/tabs/-/tabs-3.3.7.tgz" integrity sha512-ZdLe5xOcFX6+/ni45Dl2jO0jFATpTnoSqj6kLIS/BYv8oh0n817OjJkLf+DS3CLfNjApJWrHqAk34xNh6nRnEg== dependencies: "@react-types/shared" "^3.23.1" -"@react-types/textfield@^3.9.3", "@react-types/textfield@3.9.3": +"@react-types/textfield@3.9.3", "@react-types/textfield@^3.9.3": version "3.9.3" resolved "https://registry.npmjs.org/@react-types/textfield/-/textfield-3.9.3.tgz" integrity sha512-DoAY6cYOL0pJhgNGI1Rosni7g72GAt4OVr2ltEx2S9ARmFZ0DBvdhA9lL2nywcnKMf27PEJcKMXzXc10qaHsJw== dependencies: "@react-types/shared" "^3.23.1" -"@react-types/tooltip@^3.4.9", "@react-types/tooltip@3.4.9": +"@react-types/tooltip@3.4.9", "@react-types/tooltip@^3.4.9": version "3.4.9" resolved "https://registry.npmjs.org/@react-types/tooltip/-/tooltip-3.4.9.tgz" integrity sha512-wZ+uF1+Zc43qG+cOJzioBmLUNjRa7ApdcT0LI1VvaYvH5GdfjzUJOorLX9V/vAci0XMJ50UZ+qsh79aUlw2yqg== @@ -2531,7 +2539,7 @@ resolved "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz" integrity sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ== -"@swc/helpers@^0.5.0", "@swc/helpers@0.5.5": +"@swc/helpers@0.5.5", "@swc/helpers@^0.5.0": version "0.5.5" resolved "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.5.tgz" integrity sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A== @@ -4037,7 +4045,7 @@ dependencies: "@types/react" "*" -"@types/react@*", "@types/react@^16.8.0 || ^17.0.0 || ^18.0.0", "@types/react@^16.9.0 || ^17.0.0 || ^18.0.0": +"@types/react@*": version "18.3.11" resolved "https://registry.npmjs.org/@types/react/-/react-18.3.11.tgz" integrity sha512-r6QZ069rFTjrEYgFdOck1gK7FLVsgJE7tTz0pQBczlBNUhBNk0MQH4UbnFSwjpQLMkLzgqvBBa+qGpLje16eTQ== @@ -4058,6 +4066,11 @@ abab@^2.0.5, abab@^2.0.6: resolved "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz" integrity sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA== +abbrev@1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== + abort-controller@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz" @@ -4108,13 +4121,6 @@ ag-grid-react@^32.0.2: ag-grid-community "32.1.0" prop-types "^15.8.1" -agent-base@^7.0.2, agent-base@^7.1.0: - version "7.1.1" - resolved "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz" - integrity sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA== - dependencies: - debug "^4.3.4" - agent-base@6: version "6.0.2" resolved "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz" @@ -4122,6 +4128,13 @@ agent-base@6: dependencies: debug "4" +agent-base@^7.0.2, agent-base@^7.1.0: + version "7.1.1" + resolved "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz" + integrity sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA== + dependencies: + debug "^4.3.4" + ansi-regex@^5.0.1: version "5.0.1" resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz" @@ -4164,6 +4177,19 @@ anymatch@~3.1.2: normalize-path "^3.0.0" picomatch "^2.0.4" +"aproba@^1.0.3 || ^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc" + integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ== + +are-we-there-yet@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz#372e0e7bd279d8e94c653aaa1f67200884bf3e1c" + integrity sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw== + dependencies: + delegates "^1.0.0" + readable-stream "^3.6.0" + arg@^5.0.2: version "5.0.2" resolved "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz" @@ -4231,6 +4257,14 @@ body-scroll-lock@^3.1.5: resolved "https://registry.npmjs.org/body-scroll-lock/-/body-scroll-lock-3.1.5.tgz" integrity sha512-Yi1Xaml0EvNA0OYWxXiYNqY24AfWkbA6w5vxE7GWxtKfzIbZM+Qw+aSmkgsbWzbHiy/RCSkUZBplVxTA+E4jJg== +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + brace-expansion@^2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz" @@ -4285,6 +4319,15 @@ caniuse-lite@^1.0.30001579: resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001634.tgz" integrity sha512-fbBYXQ9q3+yp1q1gBk86tOFs4pyn/yxFm5ZNP18OXJDfA3txImOY9PhfxVggZ4vRHDqoU8NrKU81eN0OtzOgRA== +canvas@^2.8.0: + version "2.11.2" + resolved "https://registry.yarnpkg.com/canvas/-/canvas-2.11.2.tgz#553d87b1e0228c7ac0fc72887c3adbac4abbd860" + integrity sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw== + dependencies: + "@mapbox/node-pre-gyp" "^1.0.0" + nan "^2.17.0" + simple-get "^3.0.3" + chalk@^2.4.2: version "2.4.2" resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" @@ -4294,7 +4337,7 @@ chalk@^2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chokidar@^3.5.3, "chokidar@>=3.0.0 <4.0.0": +"chokidar@>=3.0.0 <4.0.0", chokidar@^3.5.3: version "3.6.0" resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz" integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== @@ -4309,22 +4352,22 @@ chokidar@^3.5.3, "chokidar@>=3.0.0 <4.0.0": optionalDependencies: fsevents "~2.3.2" +chownr@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" + integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== + classnames@^2.3.1: version "2.5.1" resolved "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz" integrity sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow== -client-only@^0.0.1, client-only@0.0.1: +client-only@0.0.1, client-only@^0.0.1: version "0.0.1" resolved "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz" integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA== -clsx@^1.1.1: - version "1.2.1" - resolved "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz" - integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg== - -clsx@^1.2.1: +clsx@^1.1.1, clsx@^1.2.1: version "1.2.1" resolved "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz" integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg== @@ -4348,16 +4391,16 @@ color-convert@^2.0.1: dependencies: color-name "~1.1.4" -color-name@^1.0.0, color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - color-name@1.1.3: version "1.1.3" resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== +color-name@^1.0.0, color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + color-string@^1.9.0: version "1.9.1" resolved "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz" @@ -4366,6 +4409,16 @@ color-string@^1.9.0: color-name "^1.0.0" simple-swizzle "^0.2.2" +color-support@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" + integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== + +color2k@^2.0.2: + version "2.0.3" + resolved "https://registry.npmjs.org/color2k/-/color2k-2.0.3.tgz" + integrity sha512-zW190nQTIoXcGCaU08DvVNFTmQhUpnJfVuAKfWqUQkflXKpaDdpaYoM0iluLS9lgJNHyBF58KKA2FBEwkD7wog== + color@^4.2.3: version "4.2.3" resolved "https://registry.npmjs.org/color/-/color-4.2.3.tgz" @@ -4374,11 +4427,6 @@ color@^4.2.3: color-convert "^2.0.1" color-string "^1.9.0" -color2k@^2.0.2: - version "2.0.3" - resolved "https://registry.npmjs.org/color2k/-/color2k-2.0.3.tgz" - integrity sha512-zW190nQTIoXcGCaU08DvVNFTmQhUpnJfVuAKfWqUQkflXKpaDdpaYoM0iluLS9lgJNHyBF58KKA2FBEwkD7wog== - combined-stream@^1.0.8: version "1.0.8" resolved "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz" @@ -4386,6 +4434,11 @@ combined-stream@^1.0.8: dependencies: delayed-stream "~1.0.0" +commander@2: + version "2.20.3" + resolved "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + commander@^11.0.0: version "11.1.0" resolved "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz" @@ -4396,11 +4449,6 @@ commander@^4.0.0: resolved "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz" integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== -commander@2: - version "2.20.3" - resolved "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz" - integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== - complex.js@^2.1.1: version "2.1.1" resolved "https://registry.npmjs.org/complex.js/-/complex.js-2.1.1.tgz" @@ -4411,6 +4459,11 @@ compute-scroll-into-view@^3.0.2: resolved "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-3.1.0.tgz" integrity sha512-rj8l8pD4bJ1nx+dAkMhV1xB5RuZEyVysfxJqB1pRchh1KVvwOv9b7CGB8ZfjTImVv2oF+sYMUkMZq6Na5Ftmbg== +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + concaveman@^1.2.1: version "1.2.1" resolved "https://registry.npmjs.org/concaveman/-/concaveman-1.2.1.tgz" @@ -4421,6 +4474,11 @@ concaveman@^1.2.1: robust-predicates "^2.0.4" tinyqueue "^2.0.3" +console-control-strings@^1.0.0, console-control-strings@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ== + convert-source-map@^1.5.0: version "1.9.0" resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz" @@ -4521,6 +4579,13 @@ dayjs@^1.11.13: resolved "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz" integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg== +debug@4, debug@^4.3.3, debug@^4.3.4: + version "4.3.5" + resolved "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz" + integrity sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg== + dependencies: + ms "2.1.2" + debug@^4.3.1: version "4.3.7" resolved "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz" @@ -4528,18 +4593,18 @@ debug@^4.3.1: dependencies: ms "^2.1.3" -debug@^4.3.3, debug@^4.3.4, debug@4: - version "4.3.5" - resolved "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz" - integrity sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg== - dependencies: - ms "2.1.2" - decimal.js@^10.3.1, decimal.js@^10.4.3: version "10.4.3" resolved "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz" integrity sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA== +decompress-response@^4.2.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-4.2.1.tgz#414023cc7a302da25ce2ec82d0d5238ccafd8986" + integrity sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw== + dependencies: + mimic-response "^2.0.0" + deepmerge@4.3.1: version "4.3.1" resolved "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz" @@ -4555,6 +4620,16 @@ delayed-stream@~1.0.0: resolved "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz" integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ== + +detect-libc@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.3.tgz#f0cd503b40f9939b894697d19ad50895e30cf700" + integrity sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw== + detect-node-es@^1.1.0: version "1.1.0" resolved "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz" @@ -4745,13 +4820,25 @@ fraction.js@^4.3.7: resolved "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz" integrity sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew== -framer-motion@^11.2.13, framer-motion@>=10.17.0: +framer-motion@^11.2.13: version "11.3.21" resolved "https://registry.npmjs.org/framer-motion/-/framer-motion-11.3.21.tgz" integrity sha512-D+hfIsvzV8eL/iycld4K+tKlg2Q2LdwnrcBEohtGw3cG1AIuNYATbT5RUqIM1ndsAk+EfGhoSGf0UaiFodc5Tw== dependencies: tslib "^2.4.0" +fs-minipass@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" + integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== + dependencies: + minipass "^3.0.0" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + fs@^0.0.1-security: version "0.0.1-security" resolved "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz" @@ -4767,6 +4854,21 @@ function-bind@^1.1.2: resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz" integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== +gauge@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-3.0.2.tgz#03bf4441c044383908bcfa0656ad91803259b395" + integrity sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q== + dependencies: + aproba "^1.0.3 || ^2.0.0" + color-support "^1.1.2" + console-control-strings "^1.0.0" + has-unicode "^2.0.1" + object-assign "^4.1.1" + signal-exit "^3.0.0" + string-width "^4.2.3" + strip-ansi "^6.0.1" + wide-align "^1.1.2" + geojson-equality-ts@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/geojson-equality-ts/-/geojson-equality-ts-1.0.2.tgz" @@ -4811,6 +4913,18 @@ glob@^10.3.10: minipass "^7.1.2" path-scurry "^1.11.1" +glob@^7.1.3: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + globals@^11.1.0: version "11.12.0" resolved "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz" @@ -4831,6 +4945,11 @@ has-flag@^3.0.0: resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== +has-unicode@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + integrity sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ== + hasown@^2.0.0: version "2.0.2" resolved "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz" @@ -4885,7 +5004,7 @@ https-proxy-agent@^7.0.0: agent-base "^7.0.2" debug "4" -iconv-lite@^0.6.3, iconv-lite@0.6.3: +iconv-lite@0.6.3, iconv-lite@^0.6.3: version "0.6.3" resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz" integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== @@ -4910,9 +5029,17 @@ import-fresh@^3.2.1: parent-module "^1.0.0" resolve-from "^4.0.0" -inherits@^2.0.4: +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@^2.0.3, inherits@^2.0.4: version "2.0.4" - resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== international-types@^0.8.1: @@ -5243,6 +5370,13 @@ lru-cache@^10.2.0: resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz" integrity sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ== +make-dir@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== + dependencies: + semver "^6.0.0" + marchingsquares@^1.3.3: version "1.3.3" resolved "https://registry.npmjs.org/marchingsquares/-/marchingsquares-1.3.3.tgz" @@ -5293,6 +5427,18 @@ mime-types@^2.1.12: dependencies: mime-db "1.52.0" +mimic-response@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-2.1.0.tgz#d13763d35f613d09ec37ebb30bac0469c0ee8f43" + integrity sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA== + +minimatch@^3.1.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + minimatch@^9.0.4: version "9.0.4" resolved "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz" @@ -5300,17 +5446,37 @@ minimatch@^9.0.4: dependencies: brace-expansion "^2.0.1" -"minipass@^5.0.0 || ^6.0.2 || ^7.0.0": +minipass@^3.0.0: + version "3.3.6" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.6.tgz#7bba384db3a1520d18c9c0e5251c3444e95dd94a" + integrity sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw== + dependencies: + yallist "^4.0.0" + +minipass@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-5.0.0.tgz#3e9788ffb90b694a5d0ec94479a45b5d8738133d" + integrity sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ== + +"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.1.2: version "7.1.2" resolved "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz" integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== -minipass@^7.1.2: - version "7.1.2" - resolved "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz" - integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== +minizlib@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" + integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== + dependencies: + minipass "^3.0.0" + yallist "^4.0.0" -ms@^2.1.1, ms@2.1.2: +mkdirp@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + +ms@2.1.2, ms@^2.1.1: version "2.1.2" resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== @@ -5341,6 +5507,11 @@ mz@^2.7.0: object-assign "^4.0.1" thenify-all "^1.0.0" +nan@^2.17.0: + version "2.22.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.22.0.tgz#31bc433fc33213c97bad36404bb68063de604de3" + integrity sha512-nbajikzWTMwsW+eSsNm3QwlOs7het9gGJU5dDZzRTQGk03vyBOauxgI4VakDzE0PtsGTmXPsXTbbjVhRwR5mpw== + nanoid@^3.3.6, nanoid@^3.3.7: version "3.3.7" resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz" @@ -5383,11 +5554,35 @@ next@14.2.3: "@next/swc-win32-ia32-msvc" "14.2.3" "@next/swc-win32-x64-msvc" "14.2.3" +node-fetch@^2.6.7: + version "2.7.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== + dependencies: + whatwg-url "^5.0.0" + +nopt@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-5.0.0.tgz#530942bb58a512fccafe53fe210f13a25355dc88" + integrity sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ== + dependencies: + abbrev "1" + normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== +npmlog@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-5.0.1.tgz#f06678e80e29419ad67ab964e0fa69959c1eb8b0" + integrity sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw== + dependencies: + are-we-there-yet "^2.0.0" + console-control-strings "^1.1.0" + gauge "^3.0.0" + set-blocking "^2.0.0" + nwsapi@^2.2.0: version "2.2.10" resolved "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.10.tgz" @@ -5403,6 +5598,13 @@ object-hash@^3.0.0: resolved "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz" integrity sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw== +once@^1.3.0, once@^1.3.1: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + open@^8.0.0: version "8.4.2" resolved "https://registry.npmjs.org/open/-/open-8.4.2.tgz" @@ -5434,6 +5636,11 @@ parse5@6.0.1: resolved "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz" integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + path-key@^3.1.0: version "3.1.1" resolved "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz" @@ -5539,15 +5746,6 @@ postcss-value-parser@^4.0.0: resolved "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz" integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== -postcss@^8, postcss@^8.0.0, postcss@^8.2.14, postcss@^8.4.21, postcss@^8.4.23, postcss@>=8.0.9: - version "8.4.38" - resolved "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz" - integrity sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A== - dependencies: - nanoid "^3.3.7" - picocolors "^1.0.0" - source-map-js "^1.2.0" - postcss@8.4.31: version "8.4.31" resolved "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz" @@ -5557,6 +5755,15 @@ postcss@8.4.31: picocolors "^1.0.0" source-map-js "^1.0.2" +postcss@^8, postcss@^8.4.23: + version "8.4.38" + resolved "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz" + integrity sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A== + dependencies: + nanoid "^3.3.7" + picocolors "^1.0.0" + source-map-js "^1.2.0" + prettier@^3.3.3: version "3.3.3" resolved "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz" @@ -5646,7 +5853,7 @@ react-datepicker@^7.3.0: prop-types "^15.7.2" react-onclickoutside "^6.13.0" -"react-dom@^15.5.x || ^16.x || ^17.x || ^18.x", "react-dom@^16.3.0 || ^17.0.0 || ^18.0.0", "react-dom@^16.8.0 || ^17 || ^18", "react-dom@^16.8.0 || ^17.0.0 || ^18.0.0", "react-dom@^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", "react-dom@^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0", "react-dom@^16.9.0 || ^17 || ^18", react-dom@^18, react-dom@^18.0.0, react-dom@^18.2.0, "react-dom@>= 16.3.0", react-dom@>=16.6.0, react-dom@>=16.8.0, react-dom@>=18: +react-dom@^18: version "18.3.1" resolved "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz" integrity sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw== @@ -5758,7 +5965,7 @@ react-transition-group@^4.3.0: loose-envify "^1.4.0" prop-types "^15.6.2" -react@*, "react@^15.5.x || ^16.x || ^17.x || ^18.x", "react@^16.3.0 || ^17.0.0 || ^18.0.0", "react@^16.8 || ^17 || ^18", "react@^16.8.0 || ^17 || ^18", "react@^16.8.0 || ^17 || ^18 || ^19", "react@^16.8.0 || ^17.0.0 || ^18.0.0", "react@^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", "react@^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0", "react@^16.9.0 || ^17 || ^18", react@^18, react@^18.0.0, react@^18.2.0, react@^18.3.1, "react@>= 16.3.0", "react@>= 16.8.0 || 17.x.x || ^18.0.0-0", react@>=16.13.1, react@>=16.6.0, react@>=16.8, react@>=16.8.0, react@>=18: +react@^18: version "18.3.1" resolved "https://registry.npmjs.org/react/-/react-18.3.1.tgz" integrity sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ== @@ -5772,6 +5979,15 @@ read-cache@^1.0.0: dependencies: pify "^2.3.0" +readable-stream@^3.6.0: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + readable-stream@^4.2.0: version "4.5.2" resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz" @@ -5831,6 +6047,13 @@ rfdc@^1.3.0: resolved "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz" integrity sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA== +rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + robust-predicates@^2.0.4: version "2.0.4" resolved "https://registry.npmjs.org/robust-predicates/-/robust-predicates-2.0.4.tgz" @@ -5863,7 +6086,7 @@ safe-buffer@~5.1.1: resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -sass@^1.3.0, sass@^1.77.8: +sass@^1.77.8: version "1.77.8" resolved "https://registry.npmjs.org/sass/-/sass-1.77.8.tgz" integrity sha512-4UHg6prsrycW20fqLGPShtEvo/WyHRVRHwOP4DzkUrObWoWI05QBSfzU71TVB7PFaL104TwNaHpjlWXAZbQiNQ== @@ -5898,6 +6121,16 @@ seedrandom@^3.0.5: resolved "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz" integrity sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg== +semver@^6.0.0: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +semver@^7.3.5: + version "7.6.3" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" + integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== + semver@^7.5.4: version "7.6.2" resolved "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz" @@ -5908,6 +6141,11 @@ server-only@^0.0.1: resolved "https://registry.npmjs.org/server-only/-/server-only-0.0.1.tgz" integrity sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA== +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== + shebang-command@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz" @@ -5920,11 +6158,30 @@ shebang-regex@^3.0.0: resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== +signal-exit@^3.0.0: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + signal-exit@^4.0.1: version "4.1.0" resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz" integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== +simple-concat@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f" + integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q== + +simple-get@^3.0.3: + version "3.1.1" + resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-3.1.1.tgz#cc7ba77cfbe761036fbfce3d021af25fc5584d55" + integrity sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA== + dependencies: + decompress-response "^4.2.0" + once "^1.3.1" + simple-concat "^1.0.0" + simple-swizzle@^0.2.2: version "0.2.2" resolved "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz" @@ -5937,7 +6194,7 @@ skmeans@0.9.7: resolved "https://registry.npmjs.org/skmeans/-/skmeans-0.9.7.tgz" integrity sha512-hNj1/oZ7ygsfmPZ7ZfN5MUBRoGg1gtpnImuJBgLO0ljQ67DtJuiQaiYdS4lUA6s0KCwnPhGivtC/WRwIZLkHyg== -source-map-js@^1.0.2, source-map-js@^1.2.0, "source-map-js@>=0.6.2 <2.0.0": +"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.2, source-map-js@^1.2.0: version "1.2.0" resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz" integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg== @@ -5972,13 +6229,6 @@ streamsearch@^1.1.0: resolved "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz" integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg== -string_decoder@^1.3.0: - version "1.3.0" - resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz" - integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== - dependencies: - safe-buffer "~5.2.0" - "string-width-cjs@npm:string-width@^4.2.0": version "4.2.3" resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" @@ -5988,16 +6238,16 @@ string_decoder@^1.3.0: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" -string-width@^4.1.0: +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.3: version "4.2.3" - resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== dependencies: emoji-regex "^8.0.0" is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" -string-width@^5.0.1: +string-width@^5.0.1, string-width@^5.1.2: version "5.1.2" resolved "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz" integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== @@ -6006,14 +6256,12 @@ string-width@^5.0.1: emoji-regex "^9.2.2" strip-ansi "^7.0.1" -string-width@^5.1.2: - version "5.1.2" - resolved "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz" - integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== +string_decoder@^1.1.1, string_decoder@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== dependencies: - eastasianwidth "^0.2.0" - emoji-regex "^9.2.2" - strip-ansi "^7.0.1" + safe-buffer "~5.2.0" "strip-ansi-cjs@npm:strip-ansi@^6.0.1": version "6.0.1" @@ -6085,7 +6333,7 @@ sweetalert2-react-content@^5.0.7: resolved "https://registry.npmjs.org/sweetalert2-react-content/-/sweetalert2-react-content-5.0.7.tgz" integrity sha512-8Fk82Mpk45lFXpJWKIFF/lq8k/dJKDDQGFcuqVosaL/qRdViyAs5+u37LoTGfnOIvf+rfQB3PAXcp1XLLn+0ew== -sweetalert2@^11.0.0, sweetalert2@^11.14.1: +sweetalert2@^11.14.1: version "11.14.1" resolved "https://registry.npmjs.org/sweetalert2/-/sweetalert2-11.14.1.tgz" integrity sha512-xadhfcA4STGMh8nC5zHFFWURhRpWc4zyI3GdMDFH/m3hGWZeQQNWhX9xcG4lI9gZYsi/IlazKbwvvje3juL3Xg== @@ -6112,7 +6360,7 @@ tailwind-variants@^0.1.20: dependencies: tailwind-merge "^1.14.0" -tailwindcss@*, tailwindcss@^3.4.1, tailwindcss@>=3.4.0: +tailwindcss@^3.4.1: version "3.4.4" resolved "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.4.tgz" integrity sha512-ZoyXOdJjISB7/BcLTR6SEsLgKtDStYyYZVLsUtWChO4Ps20CBad7lfJKVDiejocV4ME1hLmyY0WJE3hSDcmQ2A== @@ -6140,6 +6388,18 @@ tailwindcss@*, tailwindcss@^3.4.1, tailwindcss@>=3.4.0: resolve "^1.22.2" sucrase "^3.32.0" +tar@^6.1.11: + version "6.2.1" + resolved "https://registry.yarnpkg.com/tar/-/tar-6.2.1.tgz#717549c541bc3c2af15751bea94b1dd068d4b03a" + integrity sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A== + dependencies: + chownr "^2.0.0" + fs-minipass "^2.0.0" + minipass "^5.0.0" + minizlib "^2.1.1" + mkdirp "^1.0.3" + yallist "^4.0.0" + tarn@^3.0.2: version "3.0.2" resolved "https://registry.npmjs.org/tarn/-/tarn-3.0.2.tgz" @@ -6228,6 +6488,11 @@ tr46@^3.0.0: dependencies: punycode "^2.1.1" +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== + ts-interface-checker@^0.1.9: version "0.1.13" resolved "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz" @@ -6298,9 +6563,9 @@ use-sidecar@^1.1.2: detect-node-es "^1.1.0" tslib "^2.0.0" -util-deprecate@^1.0.2: +util-deprecate@^1.0.1, util-deprecate@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== uuid@^10.0.0: @@ -6327,6 +6592,11 @@ w3c-xmlserializer@^3.0.0: dependencies: xml-name-validator "^4.0.0" +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== + webidl-conversions@^7.0.0: version "7.0.0" resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz" @@ -6360,6 +6630,14 @@ whatwg-url@^11.0.0: tr46 "^3.0.0" webidl-conversions "^7.0.0" +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + which@^2.0.1: version "2.0.2" resolved "https://registry.npmjs.org/which/-/which-2.0.2.tgz" @@ -6367,6 +6645,13 @@ which@^2.0.1: dependencies: isexe "^2.0.0" +wide-align@^1.1.2: + version "1.1.5" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3" + integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg== + dependencies: + string-width "^1.0.2 || 2 || 3 || 4" + "wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" @@ -6385,6 +6670,11 @@ wrap-ansi@^8.1.0: string-width "^5.0.1" strip-ansi "^7.0.1" +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + ws@^8.2.3: version "8.17.1" resolved "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz" @@ -6400,6 +6690,11 @@ xmlchars@^2.2.0: resolved "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz" integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + yaml@^1.10.0: version "1.10.2" resolved "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz" From d2c4e169b1195e03aa75aa55f690dcd7371745ef Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Fri, 1 Nov 2024 17:43:15 +0900 Subject: [PATCH 04/51] =?UTF-8?q?fix:=20=EB=8F=84=EB=A9=B4=EC=9D=84=20?= =?UTF-8?q?=EC=9D=B4=EB=AF=B8=EC=A7=80=EB=A1=9C=20=EC=BB=A8=EB=B2=84?= =?UTF-8?q?=ED=8C=85=20=ED=9B=84=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EC=97=85?= =?UTF-8?q?=EB=A1=9C=EB=93=9C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../placementShape/PlacementShapeSetting.jsx | 4 +-- src/hooks/common/useRefFiles.js | 30 ++++++++++++++++++- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx b/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx index 539dbdf1..2052bff9 100644 --- a/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx +++ b/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx @@ -19,7 +19,7 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set const [canvasSetting, setCanvasSetting] = useRecoilState(canvasSettingState) const { closePopup } = usePopup() const [basicSetting, setBasicSettings] = useRecoilState(basicSettingState) - const { refImage, setRefImage } = useRefFiles() + const { refImage, setRefImage, handleRefFile } = useRefFiles() const { getMessage } = useMessage() const { get, post } = useAxios() @@ -490,7 +490,7 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set {getMessage('common.input.file.load')} - setRefImage(e.target.files[0])} /> + handleRefFile(e.target.files[0])} />
diff --git a/src/hooks/common/useRefFiles.js b/src/hooks/common/useRefFiles.js index 8cb046d5..c241b1e0 100644 --- a/src/hooks/common/useRefFiles.js +++ b/src/hooks/common/useRefFiles.js @@ -1,11 +1,39 @@ import { useState } from 'react' +import { convertDwgToPng } from '@/lib/cadAction' +import { useSwal } from '@/hooks/useSwal' export default function useRefFiles() { - const [refImage, setRefImage] = useState(null) const converterUrl = process.env.NEXT_PUBLIC_CONVERTER_API_URL + const [refImage, setRefImage] = useState(null) + + const { swalFire } = useSwal() + + const handleRefFile = (file) => { + setRefImage(file) + console.log('🚀 ~ handleRefFile ~ file:', file) + file.name.split('.').pop() === 'dwg' ? handleUploadRefFile(file) : () => {} + console.log("🚀 ~ handleRefFile ~ file.name.split('.').pop():", file.name.split('.').pop()) + // handleUploadRefFile(file) + } + + // RefFile이 캐드 도면 파일일 경우 변환하여 이미지로 저장 + const handleUploadRefFile = async (file) => { + const formData = new FormData() + formData.append('file', file) + + await promisePost({ url: converterUrl, data: formData }) + .then((res) => { + convertDwgToPng(res.data.Files[0].FileName, res.data.Files[0].FileData) + swalFire({ text: '파일 변환 성공' }) + }) + .catch((err) => { + swalFire({ text: '파일 변환 실패', icon: 'error' }) + }) + } return { refImage, setRefImage, + handleRefFile, } } From 56916a884f90040f33cc15b3b893a9ed3e6539eb Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Mon, 4 Nov 2024 17:15:50 +0900 Subject: [PATCH 05/51] feat: add canvas bg attribute --- src/hooks/usePlan.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/hooks/usePlan.js b/src/hooks/usePlan.js index bddebc63..c1708a37 100644 --- a/src/hooks/usePlan.js +++ b/src/hooks/usePlan.js @@ -189,6 +189,8 @@ export function usePlan() { userId: item.userId, canvasStatus: dbToCanvasFormat(item.canvasStatus), isCurrent: false, + bgImageName: item.bgImageName, + bgCadfileName: item.bgCadfileName, })), ) } From b1f16e55e3ca2abc5639e224902a7c9ba7f196bb Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Fri, 1 Nov 2024 13:21:55 +0900 Subject: [PATCH 06/51] feat: Add floor-plan image load feature --- .../modal/placementShape/PlacementShapeSetting.jsx | 9 +++++---- src/hooks/common/useRefFiles.js | 11 +++++++++++ 2 files changed, 16 insertions(+), 4 deletions(-) create mode 100644 src/hooks/common/useRefFiles.js diff --git a/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx b/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx index 99b72eb4..539dbdf1 100644 --- a/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx +++ b/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx @@ -9,6 +9,7 @@ import { useAxios } from '@/hooks/useAxios' import { useSwal } from '@/hooks/useSwal' import { usePopup } from '@/hooks/usePopup' import { basicSettingState } from '@/store/settingAtom' +import useRefFiles from '@/hooks/common/useRefFiles' export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, setShowPlaceShapeModal }) { const [objectNo, setObjectNo] = useState('test123241008001') // 후에 삭제 필요 @@ -18,7 +19,7 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set const [canvasSetting, setCanvasSetting] = useRecoilState(canvasSettingState) const { closePopup } = usePopup() const [basicSetting, setBasicSettings] = useRecoilState(basicSettingState) - const [image, setImage] = useState(null) + const { refImage, setRefImage } = useRefFiles() const { getMessage } = useMessage() const { get, post } = useAxios() @@ -489,11 +490,11 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set {getMessage('common.input.file.load')} - setImage(e.target.files[0])} /> + setRefImage(e.target.files[0])} />
- - {image && } + + {refImage && }
diff --git a/src/hooks/common/useRefFiles.js b/src/hooks/common/useRefFiles.js new file mode 100644 index 00000000..8cb046d5 --- /dev/null +++ b/src/hooks/common/useRefFiles.js @@ -0,0 +1,11 @@ +import { useState } from 'react' + +export default function useRefFiles() { + const [refImage, setRefImage] = useState(null) + const converterUrl = process.env.NEXT_PUBLIC_CONVERTER_API_URL + + return { + refImage, + setRefImage, + } +} From b2fb1660292447cf525609dc2aff9490efe5bb63 Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Fri, 1 Nov 2024 17:43:15 +0900 Subject: [PATCH 07/51] =?UTF-8?q?fix:=20=EB=8F=84=EB=A9=B4=EC=9D=84=20?= =?UTF-8?q?=EC=9D=B4=EB=AF=B8=EC=A7=80=EB=A1=9C=20=EC=BB=A8=EB=B2=84?= =?UTF-8?q?=ED=8C=85=20=ED=9B=84=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EC=97=85?= =?UTF-8?q?=EB=A1=9C=EB=93=9C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../placementShape/PlacementShapeSetting.jsx | 4 +-- src/hooks/common/useRefFiles.js | 30 ++++++++++++++++++- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx b/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx index 539dbdf1..2052bff9 100644 --- a/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx +++ b/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx @@ -19,7 +19,7 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set const [canvasSetting, setCanvasSetting] = useRecoilState(canvasSettingState) const { closePopup } = usePopup() const [basicSetting, setBasicSettings] = useRecoilState(basicSettingState) - const { refImage, setRefImage } = useRefFiles() + const { refImage, setRefImage, handleRefFile } = useRefFiles() const { getMessage } = useMessage() const { get, post } = useAxios() @@ -490,7 +490,7 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set {getMessage('common.input.file.load')} - setRefImage(e.target.files[0])} /> + handleRefFile(e.target.files[0])} />
diff --git a/src/hooks/common/useRefFiles.js b/src/hooks/common/useRefFiles.js index 8cb046d5..c241b1e0 100644 --- a/src/hooks/common/useRefFiles.js +++ b/src/hooks/common/useRefFiles.js @@ -1,11 +1,39 @@ import { useState } from 'react' +import { convertDwgToPng } from '@/lib/cadAction' +import { useSwal } from '@/hooks/useSwal' export default function useRefFiles() { - const [refImage, setRefImage] = useState(null) const converterUrl = process.env.NEXT_PUBLIC_CONVERTER_API_URL + const [refImage, setRefImage] = useState(null) + + const { swalFire } = useSwal() + + const handleRefFile = (file) => { + setRefImage(file) + console.log('🚀 ~ handleRefFile ~ file:', file) + file.name.split('.').pop() === 'dwg' ? handleUploadRefFile(file) : () => {} + console.log("🚀 ~ handleRefFile ~ file.name.split('.').pop():", file.name.split('.').pop()) + // handleUploadRefFile(file) + } + + // RefFile이 캐드 도면 파일일 경우 변환하여 이미지로 저장 + const handleUploadRefFile = async (file) => { + const formData = new FormData() + formData.append('file', file) + + await promisePost({ url: converterUrl, data: formData }) + .then((res) => { + convertDwgToPng(res.data.Files[0].FileName, res.data.Files[0].FileData) + swalFire({ text: '파일 변환 성공' }) + }) + .catch((err) => { + swalFire({ text: '파일 변환 실패', icon: 'error' }) + }) + } return { refImage, setRefImage, + handleRefFile, } } From f71cc701c29f7064796ded6dd19fbebdb1f67619 Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Mon, 4 Nov 2024 17:15:50 +0900 Subject: [PATCH 08/51] feat: add canvas bg attribute --- src/hooks/usePlan.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/hooks/usePlan.js b/src/hooks/usePlan.js index bddebc63..c1708a37 100644 --- a/src/hooks/usePlan.js +++ b/src/hooks/usePlan.js @@ -189,6 +189,8 @@ export function usePlan() { userId: item.userId, canvasStatus: dbToCanvasFormat(item.canvasStatus), isCurrent: false, + bgImageName: item.bgImageName, + bgCadfileName: item.bgCadfileName, })), ) } From 3b76c53db836a250e1de6ffe4caec3ea55ce6970 Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Tue, 5 Nov 2024 15:25:25 +0900 Subject: [PATCH 09/51] rebase --- .../placementShape/PlacementShapeSetting.jsx | 95 +++++++++++++++++-- src/hooks/common/useRefFiles.js | 47 ++++++++- src/hooks/usePlan.js | 2 +- 3 files changed, 131 insertions(+), 13 deletions(-) diff --git a/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx b/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx index 2052bff9..e6f80941 100644 --- a/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx +++ b/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx @@ -1,15 +1,20 @@ -import SizeGuide from '@/components/floor-plan/modal/placementShape/SizeGuide' -import MaterialGuide from '@/components/floor-plan/modal/placementShape/MaterialGuide' -import WithDraggable from '@/components/common/draggable/WithDraggable' +import { useContext, useEffect, useState } from 'react' import { useRecoilState } from 'recoil' -import { Fragment, useEffect, useState } from 'react' + import { canvasSettingState } from '@/store/canvasAtom' +import { basicSettingState } from '@/store/settingAtom' + import { useMessage } from '@/hooks/useMessage' import { useAxios } from '@/hooks/useAxios' import { useSwal } from '@/hooks/useSwal' import { usePopup } from '@/hooks/usePopup' -import { basicSettingState } from '@/store/settingAtom' import useRefFiles from '@/hooks/common/useRefFiles' +import { usePlan } from '@/hooks/usePlan' + +import SizeGuide from '@/components/floor-plan/modal/placementShape/SizeGuide' +import MaterialGuide from '@/components/floor-plan/modal/placementShape/MaterialGuide' +import WithDraggable from '@/components/common/draggable/WithDraggable' +import { SessionContext } from '@/app/SessionProvider' export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, setShowPlaceShapeModal }) { const [objectNo, setObjectNo] = useState('test123241008001') // 후에 삭제 필요 @@ -19,7 +24,18 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set const [canvasSetting, setCanvasSetting] = useRecoilState(canvasSettingState) const { closePopup } = usePopup() const [basicSetting, setBasicSettings] = useRecoilState(basicSettingState) - const { refImage, setRefImage, handleRefFile } = useRefFiles() + const { + refImage, + setRefImage, + handleRefFile, + refFileMethod, + setRefFileMethod, + handleRefFileMethod, + mapPositionAddress, + setMapPositionAddress, + handleFileDelete, + } = useRefFiles() + const { currentCanvasPlan } = usePlan() const { getMessage } = useMessage() const { get, post } = useAxios() @@ -484,7 +500,70 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set {getMessage('common.input.file')} -
+
+
+ handleRefFileMethod(e)} + checked={refFileMethod === '1'} + /> + +
+
+ handleRefFileMethod(e)} + checked={refFileMethod === '2'} + /> + +
+
+ + {/* 파일 불러오기 */} + {refFileMethod === '1' && ( +
+
+ + handleRefFile(e.target.files[0])} /> +
+
+ {currentCanvasPlan?.bgImageName === null ? ( + + ) : ( + + )} + {(refImage || currentCanvasPlan?.bgImageName) && } +
+
+ )} + + {/* 주소 불러오기 */} + {refFileMethod === '2' && ( +
+ setMapPositionAddress(e.target.value)} + /> +
+ +
+ + +
+ )} + {/*
-
+
*/} diff --git a/src/hooks/common/useRefFiles.js b/src/hooks/common/useRefFiles.js index c241b1e0..a1971f7b 100644 --- a/src/hooks/common/useRefFiles.js +++ b/src/hooks/common/useRefFiles.js @@ -1,22 +1,46 @@ import { useState } from 'react' -import { convertDwgToPng } from '@/lib/cadAction' import { useSwal } from '@/hooks/useSwal' +import { usePlan } from '@/hooks/usePlan' +import { convertDwgToPng } from '@/lib/cadAction' export default function useRefFiles() { const converterUrl = process.env.NEXT_PUBLIC_CONVERTER_API_URL const [refImage, setRefImage] = useState(null) + const [refFileMethod, setRefFileMethod] = useState('1') + const [mapPositionAddress, setMapPositionAddress] = useState('') const { swalFire } = useSwal() + const { currentCanvasPlan, setCurrentCanvasPlan } = usePlan() + /** + * 파일 불러오기 버튼 컨트롤 + * @param {*} file + */ const handleRefFile = (file) => { setRefImage(file) - console.log('🚀 ~ handleRefFile ~ file:', file) file.name.split('.').pop() === 'dwg' ? handleUploadRefFile(file) : () => {} - console.log("🚀 ~ handleRefFile ~ file.name.split('.').pop():", file.name.split('.').pop()) // handleUploadRefFile(file) } - // RefFile이 캐드 도면 파일일 경우 변환하여 이미지로 저장 + /** + * 파일 삭제 + */ + const handleFileDelete = () => { + setRefImage(null) + setCurrentCanvasPlan((prev) => ({ ...prev, bgFileName: null })) + } + + /** + * 주소 삭제 + */ + const handleAddressDelete = () => { + setCurrentCanvasPlan((prev) => ({ ...prev, mapPositionAddress: null })) + } + + /** + * RefFile이 캐드 도면 파일일 경우 변환하여 이미지로 저장 + * @param {*} file + */ const handleUploadRefFile = async (file) => { const formData = new FormData() formData.append('file', file) @@ -31,9 +55,24 @@ export default function useRefFiles() { }) } + /** + * 라디오 버튼 컨트롤 + * @param {*} e + */ + const handleRefFileMethod = (e) => { + setRefFileMethod(e.target.value) + } + return { refImage, setRefImage, handleRefFile, + refFileMethod, + setRefFileMethod, + mapPositionAddress, + setMapPositionAddress, + handleRefFileMethod, + handleFileDelete, + handleAddressDelete, } } diff --git a/src/hooks/usePlan.js b/src/hooks/usePlan.js index c1708a37..5b78fd7c 100644 --- a/src/hooks/usePlan.js +++ b/src/hooks/usePlan.js @@ -190,7 +190,7 @@ export function usePlan() { canvasStatus: dbToCanvasFormat(item.canvasStatus), isCurrent: false, bgImageName: item.bgImageName, - bgCadfileName: item.bgCadfileName, + mapPositionAddress: item.mapPositionAddress, })), ) } From af49d7c91124bc659e522d4c66f0a9896986c852 Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Fri, 1 Nov 2024 13:21:55 +0900 Subject: [PATCH 10/51] feat: Add floor-plan image load feature --- .../modal/placementShape/PlacementShapeSetting.jsx | 9 +++++---- src/hooks/common/useRefFiles.js | 11 +++++++++++ 2 files changed, 16 insertions(+), 4 deletions(-) create mode 100644 src/hooks/common/useRefFiles.js diff --git a/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx b/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx index 99b72eb4..539dbdf1 100644 --- a/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx +++ b/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx @@ -9,6 +9,7 @@ import { useAxios } from '@/hooks/useAxios' import { useSwal } from '@/hooks/useSwal' import { usePopup } from '@/hooks/usePopup' import { basicSettingState } from '@/store/settingAtom' +import useRefFiles from '@/hooks/common/useRefFiles' export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, setShowPlaceShapeModal }) { const [objectNo, setObjectNo] = useState('test123241008001') // 후에 삭제 필요 @@ -18,7 +19,7 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set const [canvasSetting, setCanvasSetting] = useRecoilState(canvasSettingState) const { closePopup } = usePopup() const [basicSetting, setBasicSettings] = useRecoilState(basicSettingState) - const [image, setImage] = useState(null) + const { refImage, setRefImage } = useRefFiles() const { getMessage } = useMessage() const { get, post } = useAxios() @@ -489,11 +490,11 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set {getMessage('common.input.file.load')} - setImage(e.target.files[0])} /> + setRefImage(e.target.files[0])} />
- - {image && } + + {refImage && }
diff --git a/src/hooks/common/useRefFiles.js b/src/hooks/common/useRefFiles.js new file mode 100644 index 00000000..8cb046d5 --- /dev/null +++ b/src/hooks/common/useRefFiles.js @@ -0,0 +1,11 @@ +import { useState } from 'react' + +export default function useRefFiles() { + const [refImage, setRefImage] = useState(null) + const converterUrl = process.env.NEXT_PUBLIC_CONVERTER_API_URL + + return { + refImage, + setRefImage, + } +} From 42721da55802ae0fd3c7b6ae0e8635aa718ce95a Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Fri, 1 Nov 2024 17:43:15 +0900 Subject: [PATCH 11/51] =?UTF-8?q?fix:=20=EB=8F=84=EB=A9=B4=EC=9D=84=20?= =?UTF-8?q?=EC=9D=B4=EB=AF=B8=EC=A7=80=EB=A1=9C=20=EC=BB=A8=EB=B2=84?= =?UTF-8?q?=ED=8C=85=20=ED=9B=84=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EC=97=85?= =?UTF-8?q?=EB=A1=9C=EB=93=9C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../placementShape/PlacementShapeSetting.jsx | 4 +-- src/hooks/common/useRefFiles.js | 30 ++++++++++++++++++- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx b/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx index 539dbdf1..2052bff9 100644 --- a/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx +++ b/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx @@ -19,7 +19,7 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set const [canvasSetting, setCanvasSetting] = useRecoilState(canvasSettingState) const { closePopup } = usePopup() const [basicSetting, setBasicSettings] = useRecoilState(basicSettingState) - const { refImage, setRefImage } = useRefFiles() + const { refImage, setRefImage, handleRefFile } = useRefFiles() const { getMessage } = useMessage() const { get, post } = useAxios() @@ -490,7 +490,7 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set {getMessage('common.input.file.load')} - setRefImage(e.target.files[0])} /> + handleRefFile(e.target.files[0])} />
diff --git a/src/hooks/common/useRefFiles.js b/src/hooks/common/useRefFiles.js index 8cb046d5..c241b1e0 100644 --- a/src/hooks/common/useRefFiles.js +++ b/src/hooks/common/useRefFiles.js @@ -1,11 +1,39 @@ import { useState } from 'react' +import { convertDwgToPng } from '@/lib/cadAction' +import { useSwal } from '@/hooks/useSwal' export default function useRefFiles() { - const [refImage, setRefImage] = useState(null) const converterUrl = process.env.NEXT_PUBLIC_CONVERTER_API_URL + const [refImage, setRefImage] = useState(null) + + const { swalFire } = useSwal() + + const handleRefFile = (file) => { + setRefImage(file) + console.log('🚀 ~ handleRefFile ~ file:', file) + file.name.split('.').pop() === 'dwg' ? handleUploadRefFile(file) : () => {} + console.log("🚀 ~ handleRefFile ~ file.name.split('.').pop():", file.name.split('.').pop()) + // handleUploadRefFile(file) + } + + // RefFile이 캐드 도면 파일일 경우 변환하여 이미지로 저장 + const handleUploadRefFile = async (file) => { + const formData = new FormData() + formData.append('file', file) + + await promisePost({ url: converterUrl, data: formData }) + .then((res) => { + convertDwgToPng(res.data.Files[0].FileName, res.data.Files[0].FileData) + swalFire({ text: '파일 변환 성공' }) + }) + .catch((err) => { + swalFire({ text: '파일 변환 실패', icon: 'error' }) + }) + } return { refImage, setRefImage, + handleRefFile, } } From 9df450e70006421f20d8e1c36e717f0424067557 Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Mon, 4 Nov 2024 17:15:50 +0900 Subject: [PATCH 12/51] feat: add canvas bg attribute --- src/hooks/usePlan.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/hooks/usePlan.js b/src/hooks/usePlan.js index bddebc63..c1708a37 100644 --- a/src/hooks/usePlan.js +++ b/src/hooks/usePlan.js @@ -189,6 +189,8 @@ export function usePlan() { userId: item.userId, canvasStatus: dbToCanvasFormat(item.canvasStatus), isCurrent: false, + bgImageName: item.bgImageName, + bgCadfileName: item.bgCadfileName, })), ) } From 54a0becd9b70624b00a3635038c720677b52ad35 Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Tue, 5 Nov 2024 15:25:25 +0900 Subject: [PATCH 13/51] rebase --- .../placementShape/PlacementShapeSetting.jsx | 95 +++++++++++++++++-- src/hooks/common/useRefFiles.js | 47 ++++++++- src/hooks/usePlan.js | 2 +- 3 files changed, 131 insertions(+), 13 deletions(-) diff --git a/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx b/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx index 2052bff9..e6f80941 100644 --- a/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx +++ b/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx @@ -1,15 +1,20 @@ -import SizeGuide from '@/components/floor-plan/modal/placementShape/SizeGuide' -import MaterialGuide from '@/components/floor-plan/modal/placementShape/MaterialGuide' -import WithDraggable from '@/components/common/draggable/WithDraggable' +import { useContext, useEffect, useState } from 'react' import { useRecoilState } from 'recoil' -import { Fragment, useEffect, useState } from 'react' + import { canvasSettingState } from '@/store/canvasAtom' +import { basicSettingState } from '@/store/settingAtom' + import { useMessage } from '@/hooks/useMessage' import { useAxios } from '@/hooks/useAxios' import { useSwal } from '@/hooks/useSwal' import { usePopup } from '@/hooks/usePopup' -import { basicSettingState } from '@/store/settingAtom' import useRefFiles from '@/hooks/common/useRefFiles' +import { usePlan } from '@/hooks/usePlan' + +import SizeGuide from '@/components/floor-plan/modal/placementShape/SizeGuide' +import MaterialGuide from '@/components/floor-plan/modal/placementShape/MaterialGuide' +import WithDraggable from '@/components/common/draggable/WithDraggable' +import { SessionContext } from '@/app/SessionProvider' export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, setShowPlaceShapeModal }) { const [objectNo, setObjectNo] = useState('test123241008001') // 후에 삭제 필요 @@ -19,7 +24,18 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set const [canvasSetting, setCanvasSetting] = useRecoilState(canvasSettingState) const { closePopup } = usePopup() const [basicSetting, setBasicSettings] = useRecoilState(basicSettingState) - const { refImage, setRefImage, handleRefFile } = useRefFiles() + const { + refImage, + setRefImage, + handleRefFile, + refFileMethod, + setRefFileMethod, + handleRefFileMethod, + mapPositionAddress, + setMapPositionAddress, + handleFileDelete, + } = useRefFiles() + const { currentCanvasPlan } = usePlan() const { getMessage } = useMessage() const { get, post } = useAxios() @@ -484,7 +500,70 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set {getMessage('common.input.file')} -
+
+
+ handleRefFileMethod(e)} + checked={refFileMethod === '1'} + /> + +
+
+ handleRefFileMethod(e)} + checked={refFileMethod === '2'} + /> + +
+
+ + {/* 파일 불러오기 */} + {refFileMethod === '1' && ( +
+
+ + handleRefFile(e.target.files[0])} /> +
+
+ {currentCanvasPlan?.bgImageName === null ? ( + + ) : ( + + )} + {(refImage || currentCanvasPlan?.bgImageName) && } +
+
+ )} + + {/* 주소 불러오기 */} + {refFileMethod === '2' && ( +
+ setMapPositionAddress(e.target.value)} + /> +
+ +
+ + +
+ )} + {/*
-
+
*/} diff --git a/src/hooks/common/useRefFiles.js b/src/hooks/common/useRefFiles.js index c241b1e0..a1971f7b 100644 --- a/src/hooks/common/useRefFiles.js +++ b/src/hooks/common/useRefFiles.js @@ -1,22 +1,46 @@ import { useState } from 'react' -import { convertDwgToPng } from '@/lib/cadAction' import { useSwal } from '@/hooks/useSwal' +import { usePlan } from '@/hooks/usePlan' +import { convertDwgToPng } from '@/lib/cadAction' export default function useRefFiles() { const converterUrl = process.env.NEXT_PUBLIC_CONVERTER_API_URL const [refImage, setRefImage] = useState(null) + const [refFileMethod, setRefFileMethod] = useState('1') + const [mapPositionAddress, setMapPositionAddress] = useState('') const { swalFire } = useSwal() + const { currentCanvasPlan, setCurrentCanvasPlan } = usePlan() + /** + * 파일 불러오기 버튼 컨트롤 + * @param {*} file + */ const handleRefFile = (file) => { setRefImage(file) - console.log('🚀 ~ handleRefFile ~ file:', file) file.name.split('.').pop() === 'dwg' ? handleUploadRefFile(file) : () => {} - console.log("🚀 ~ handleRefFile ~ file.name.split('.').pop():", file.name.split('.').pop()) // handleUploadRefFile(file) } - // RefFile이 캐드 도면 파일일 경우 변환하여 이미지로 저장 + /** + * 파일 삭제 + */ + const handleFileDelete = () => { + setRefImage(null) + setCurrentCanvasPlan((prev) => ({ ...prev, bgFileName: null })) + } + + /** + * 주소 삭제 + */ + const handleAddressDelete = () => { + setCurrentCanvasPlan((prev) => ({ ...prev, mapPositionAddress: null })) + } + + /** + * RefFile이 캐드 도면 파일일 경우 변환하여 이미지로 저장 + * @param {*} file + */ const handleUploadRefFile = async (file) => { const formData = new FormData() formData.append('file', file) @@ -31,9 +55,24 @@ export default function useRefFiles() { }) } + /** + * 라디오 버튼 컨트롤 + * @param {*} e + */ + const handleRefFileMethod = (e) => { + setRefFileMethod(e.target.value) + } + return { refImage, setRefImage, handleRefFile, + refFileMethod, + setRefFileMethod, + mapPositionAddress, + setMapPositionAddress, + handleRefFileMethod, + handleFileDelete, + handleAddressDelete, } } diff --git a/src/hooks/usePlan.js b/src/hooks/usePlan.js index c1708a37..5b78fd7c 100644 --- a/src/hooks/usePlan.js +++ b/src/hooks/usePlan.js @@ -190,7 +190,7 @@ export function usePlan() { canvasStatus: dbToCanvasFormat(item.canvasStatus), isCurrent: false, bgImageName: item.bgImageName, - bgCadfileName: item.bgCadfileName, + mapPositionAddress: item.mapPositionAddress, })), ) } From 7023543fd783ddfe63486be03bcbc510b73f2beb Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Thu, 7 Nov 2024 09:31:54 +0900 Subject: [PATCH 14/51] =?UTF-8?q?feat:=20=EA=B5=AC=EA=B8=80=20=EB=A7=B5=20?= =?UTF-8?q?=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EB=8B=A4=EC=9A=B4=EB=A1=9C?= =?UTF-8?q?=EB=93=9C=20=EB=B0=8F=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EC=97=85?= =?UTF-8?q?=EB=A1=9C=EB=93=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/api/html2canvas/route.js | 1 - .../placementShape/PlacementShapeSetting.jsx | 13 ++++-- src/hooks/common/useRefFiles.js | 40 +++++++++++++++++-- 3 files changed, 46 insertions(+), 8 deletions(-) diff --git a/src/app/api/html2canvas/route.js b/src/app/api/html2canvas/route.js index 54af611d..02731f07 100644 --- a/src/app/api/html2canvas/route.js +++ b/src/app/api/html2canvas/route.js @@ -13,7 +13,6 @@ export async function GET(req) { const decodeUrl = decodeURIComponent(targetUrl) const response = await fetch(decodeUrl) - const data = await response.arrayBuffer() const buffer = Buffer.from(data) diff --git a/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx b/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx index 0ae1619f..c8dbdbca 100644 --- a/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx +++ b/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx @@ -1,4 +1,4 @@ -import { useContext, useEffect, useState } from 'react' +import { useEffect, useState } from 'react' import { useRecoilState } from 'recoil' import { canvasSettingState } from '@/store/canvasAtom' @@ -26,6 +26,7 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set const [basicSetting, setBasicSettings] = useRecoilState(basicSettingState) const { refImage, + queryRef, setRefImage, handleRefFile, refFileMethod, @@ -34,6 +35,7 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set mapPositionAddress, setMapPositionAddress, handleFileDelete, + handleMapImageDown, } = useRefFiles() const { currentCanvasPlan } = usePlan() @@ -557,14 +559,17 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set type="text" className="input-origin al-l mr10" placeholder={'住所入力'} + ref={queryRef} value={mapPositionAddress} onChange={(e) => setMapPositionAddress(e.target.value)} />
- +
- - + {mapPositionAddress && } + {/* */}
)} {/*
diff --git a/src/hooks/common/useRefFiles.js b/src/hooks/common/useRefFiles.js index a1971f7b..1b36a109 100644 --- a/src/hooks/common/useRefFiles.js +++ b/src/hooks/common/useRefFiles.js @@ -1,16 +1,23 @@ -import { useState } from 'react' +import { useRef, useState } from 'react' +import { useRecoilState } from 'recoil' +import { v4 as uuidv4 } from 'uuid' + import { useSwal } from '@/hooks/useSwal' -import { usePlan } from '@/hooks/usePlan' import { convertDwgToPng } from '@/lib/cadAction' +import { useAxios } from '../useAxios' +import { currentCanvasPlanState } from '@/store/canvasAtom' export default function useRefFiles() { const converterUrl = process.env.NEXT_PUBLIC_CONVERTER_API_URL const [refImage, setRefImage] = useState(null) const [refFileMethod, setRefFileMethod] = useState('1') const [mapPositionAddress, setMapPositionAddress] = useState('') + const [currentCanvasPlan, setCurrentCanvasPlan] = useRecoilState(currentCanvasPlanState) + const queryRef = useRef(null) const { swalFire } = useSwal() - const { currentCanvasPlan, setCurrentCanvasPlan } = usePlan() + const { get, promisePut } = useAxios() + // const { currentCanvasPlan, setCurrentCanvasPlan } = usePlan() /** * 파일 불러오기 버튼 컨트롤 @@ -37,6 +44,31 @@ export default function useRefFiles() { setCurrentCanvasPlan((prev) => ({ ...prev, mapPositionAddress: null })) } + /** + * 주소로 구글 맵 이미지 다운로드 + */ + const handleMapImageDown = async () => { + if (queryRef.current.value === '' || queryRef.current.value === null) { + return + } + + const res = await get({ url: `http://localhost:3000/api/html2canvas?q=${queryRef.current.value}&fileNm=${uuidv4()}&zoom=20` }) + console.log('🚀 ~ handleMapImageDown ~ res:', res) + setCurrentCanvasPlan((prev) => ({ ...prev, bgFileName: res.fileNm, mapPositionAddress: queryRef.current.value })) + } + + /** + * 현재 플랜이 변경되면 플랜 상태 저장 + */ + useEffect(() => { + const handleCurrentPlan = async () => { + await promisePut({ url: '/api/canvas-management/canvas-statuses', data: currentCanvasPlan }).then((res) => { + console.log('🚀 ~ awaitpromisePut ~ res:', res) + }) + } + handleCurrentPlan() + }, [currentCanvasPlan]) + /** * RefFile이 캐드 도면 파일일 경우 변환하여 이미지로 저장 * @param {*} file @@ -65,6 +97,7 @@ export default function useRefFiles() { return { refImage, + queryRef, setRefImage, handleRefFile, refFileMethod, @@ -74,5 +107,6 @@ export default function useRefFiles() { handleRefFileMethod, handleFileDelete, handleAddressDelete, + handleMapImageDown, } } From b94be836df97f5e6df42b74acf23ced7944d0801 Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Thu, 7 Nov 2024 10:27:25 +0900 Subject: [PATCH 15/51] chore: remove unused files --- src/app/intro/page.jsx | 12 ---- src/components/Intro.jsx | 142 --------------------------------------- src/util/session-util.js | 12 ---- 3 files changed, 166 deletions(-) delete mode 100644 src/app/intro/page.jsx delete mode 100644 src/components/Intro.jsx delete mode 100644 src/util/session-util.js diff --git a/src/app/intro/page.jsx b/src/app/intro/page.jsx deleted file mode 100644 index ebf1081b..00000000 --- a/src/app/intro/page.jsx +++ /dev/null @@ -1,12 +0,0 @@ -import Intro from '@/components/Intro' -import { initCheck } from '@/util/session-util' - -export default async function IntroPage() { - return ( - <> -
- -
- - ) -} diff --git a/src/components/Intro.jsx b/src/components/Intro.jsx deleted file mode 100644 index a6825af7..00000000 --- a/src/components/Intro.jsx +++ /dev/null @@ -1,142 +0,0 @@ -'use client' - -import { useEffect, useState } from 'react' - -import Link from 'next/link' - -import { useRecoilState } from 'recoil' -import { modalContent, modalState } from '@/store/modalAtom' - -import { useAxios } from '@/hooks/useAxios' - -import { Button } from '@nextui-org/react' - -import SingleDatePicker from './common/datepicker/SingleDatePicker' -import RangeDatePicker from './common/datepicker/RangeDatePicker' -import QGrid from './common/grid/QGrid' -import { useSwal } from '@/hooks/useSwal' - -export default function Intro() { - const { get } = useAxios() - const { swalFire } = useSwal() - - // const [open, setOpen] = useState(false) - const [startDate, setStartDate] = useState(new Date()) - const singleDatePickerProps = { - startDate, - setStartDate, - } - - const [dateRange, setDateRange] = useState([null, null]) - const [startRangeDate, endRangeDate] = dateRange - const rangeDatePickerProps = { - startRangeDate, - endRangeDate, - setDateRange, - } - - // const gridProps = { - // isPageable: false, - // } - const [gridProps, setGridProps] = useState({ - gridData: [], - isPageable: false, - }) - - const [open, setOpen] = useRecoilState(modalState) - const [contents, setContent] = useRecoilState(modalContent) - - const modelProps = { - open, - setOpen, - } - - const ipsum = ( - <> -

title

-

- 저작자·발명가·과학기술자와 예술가의 권리는 법률로써 보호한다. 이 헌법은 1988년 2월 25일부터 시행한다. 다만, 이 헌법을 시행하기 위하여 필요한 - 법률의 제정·개정과 이 헌법에 의한 대통령 및 국회의원의 선거 기타 이 헌법시행에 관한 준비는 이 헌법시행 전에 할 수 있다. -

-

- 국가는 주택개발정책등을 통하여 모든 국민이 쾌적한 주거생활을 할 수 있도록 노력하여야 한다. 통신·방송의 시설기준과 신문의 기능을 보장하기 - 위하여 필요한 사항은 법률로 정한다. -

-

- 국회에서 의결된 법률안은 정부에 이송되어 15일 이내에 대통령이 공포한다. 선거에 관한 경비는 법률이 정하는 경우를 제외하고는 정당 또는 - 후보자에게 부담시킬 수 없다. -

- - ) - - useEffect(() => { - async function fetchData() { - // const response = await fetch('https://www.ag-grid.com/example-assets/space-mission-data.json') - // const data = await response.json() - const data = await get({ url: 'https://www.ag-grid.com/example-assets/space-mission-data.json' }) - setGridProps({ ...gridProps, gridData: data }) - } - fetchData() - }, []) - - return ( - <> -
- - - -
-
-
Single Date Picker
-
- -
-
-
-
Range Date Picker
-
- -
-
-
-
QGrid
-
- -
-
-
-
QModal
-
- {/* - {ipsum} */} - -
-
-
-
QToast
-
- -
-
- - ) -} diff --git a/src/util/session-util.js b/src/util/session-util.js deleted file mode 100644 index 6f818e43..00000000 --- a/src/util/session-util.js +++ /dev/null @@ -1,12 +0,0 @@ -import { checkSession } from '@/lib/user' -import { redirect } from 'next/navigation' - -export const initCheck = async () => { - const { session } = await checkSession() - - if (!session.isLoggedIn) { - redirect('/login') - } - - return session -} From 7365279bdaae61095ab47837aa156c9fa3d92653 Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Thu, 7 Nov 2024 10:52:11 +0900 Subject: [PATCH 16/51] =?UTF-8?q?=EC=A7=80=EB=B6=95=ED=98=95=EC=83=81?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20=ED=8E=B8=EB=A5=98=20=EC=A7=80=EB=B6=95=20?= =?UTF-8?q?=EC=84=A0=ED=83=9D=20=EC=8B=9C=20=EB=B0=A9=ED=96=A5=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/roofcover/useRoofShapeSetting.js | 7 ++++++- src/hooks/useMode.js | 3 +++ src/util/qpolygon-utils.js | 6 ++++-- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/hooks/roofcover/useRoofShapeSetting.js b/src/hooks/roofcover/useRoofShapeSetting.js index 2823415d..21948de0 100644 --- a/src/hooks/roofcover/useRoofShapeSetting.js +++ b/src/hooks/roofcover/useRoofShapeSetting.js @@ -170,6 +170,7 @@ export function useRoofShapeSetting(id) { //기존 wallLine 삭제 let outerLines + let direction switch (shapeNum) { case 1: { @@ -196,6 +197,7 @@ export function useRoofShapeSetting(id) { // 서쪽 initLineSetting() outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') + direction = 'west' outerLines.forEach((line) => { setWestAndEastRoof(line) @@ -240,6 +242,7 @@ export function useRoofShapeSetting(id) { case 6: { initLineSetting() outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') + direction = 'east' outerLines.forEach((line) => { setWestAndEastRoof(line) @@ -285,6 +288,7 @@ export function useRoofShapeSetting(id) { case 7: { initLineSetting() outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') + direction = 'south' outerLines.forEach((line) => { setSouthAndNorthRoof(line) @@ -329,6 +333,7 @@ export function useRoofShapeSetting(id) { case 8: { initLineSetting() outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') + direction = 'north' outerLines.forEach((line) => { setSouthAndNorthRoof(line) @@ -389,7 +394,7 @@ export function useRoofShapeSetting(id) { canvas.remove(obj) }) - const polygon = addPolygonByLines(outerLines, { name: POLYGON_TYPE.WALL }) + const polygon = addPolygonByLines(outerLines, { name: POLYGON_TYPE.WALL, direction }) polygon.lines = [...outerLines] addPitchTextsByOuterLines() diff --git a/src/hooks/useMode.js b/src/hooks/useMode.js index 486bc8e9..6f90b028 100644 --- a/src/hooks/useMode.js +++ b/src/hooks/useMode.js @@ -1746,6 +1746,9 @@ export function useMode() { return { x1: point.x, y1: point.y } }), ) + if (wall.direction) { + roof.direction = wall.direction + } roof.name = POLYGON_TYPE.ROOF roof.setWall(wall) diff --git a/src/util/qpolygon-utils.js b/src/util/qpolygon-utils.js index e373df8d..90deebfc 100644 --- a/src/util/qpolygon-utils.js +++ b/src/util/qpolygon-utils.js @@ -1340,6 +1340,7 @@ export const splitPolygonWithLines = (polygon) => { }) const newRoofs = removeDuplicatePolygons(roofs) + newRoofs.forEach((roofPoint, index) => { let defense, pitch const polygonLines = [...polygon.lines] @@ -1378,7 +1379,8 @@ export const splitPolygonWithLines = (polygon) => { } }) - const direction = representLine.direction + const direction = newRoofs.length === 1 ? polygon.direction : representLine.direction + const polygonDirection = polygon.direction switch (direction) { case 'top': @@ -1406,7 +1408,7 @@ export const splitPolygonWithLines = (polygon) => { originY: 'center', selectable: true, defense: defense, - direction: defense, + direction: newRoofs.length === 1 ? polygonDirection : defense, pitch: pitch, }) From ee59b0498a4de27a61b82b1fe5336a791ec9b630 Mon Sep 17 00:00:00 2001 From: basssy Date: Thu, 7 Nov 2024 11:35:18 +0900 Subject: [PATCH 17/51] =?UTF-8?q?=EA=B2=AC=EC=A0=81=EC=84=9C=20=EC=83=81?= =?UTF-8?q?=EC=84=B8=20=EC=B2=A8=EB=B6=80=ED=8C=8C=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/estimate/Estimate.jsx | 60 ++++++++++++++++++++++------ 1 file changed, 47 insertions(+), 13 deletions(-) diff --git a/src/components/estimate/Estimate.jsx b/src/components/estimate/Estimate.jsx index f12d7c69..f794cb50 100644 --- a/src/components/estimate/Estimate.jsx +++ b/src/components/estimate/Estimate.jsx @@ -3,7 +3,6 @@ import { useEffect, useState, useContext } from 'react' import { useRecoilValue } from 'recoil' import { floorPlanObjectState } from '@/store/floorPlanObjectAtom' -import { SessionContext } from '@/app/SessionProvider' import { useMessage } from '@/hooks/useMessage' import { useCanvasMenu } from '@/hooks/common/useCanvasMenu' import SingleDatePicker from '../common/datepicker/SingleDatePicker' @@ -15,11 +14,15 @@ import dayjs from 'dayjs' import { useCommonCode } from '@/hooks/common/useCommonCode' import Select from 'react-select' import { useEstimateController } from '@/hooks/floorPlan/estimate/useEstimateController' +import { SessionContext } from '@/app/SessionProvider' export default function Estimate({ params }) { + const { session } = useContext(SessionContext) const [objectNo, setObjectNo] = useState('') //물건번호 const [planNo, setPlanNo] = useState('') //플랜번호 + const [files, setFiles] = useState([]) // 보내는 첨부파일 + const [originFiles, setOriginFiles] = useState([]) //기존 첨부파일 const [showContentCode, setShowContentCode] = useState('ATTR001') @@ -36,7 +39,6 @@ export default function Estimate({ params }) { setStartDate, } - const { session } = useContext(SessionContext) const objectRecoil = useRecoilValue(floorPlanObjectState) //견적서 상세데이터 @@ -48,16 +50,14 @@ export default function Estimate({ params }) { const [specialNoteList, setSpecialNoteList] = useState([]) const globalLocaleState = useRecoilValue(globalLocaleStore) - const { get, post } = useAxios(globalLocaleState) + const { get, promisePost } = useAxios(globalLocaleState) const { getMessage } = useMessage() const { setMenuNumber } = useCanvasMenu() + //새로 추가한 첨부파일 props const fileUploadProps = { - // objectNo: '', - // planNo: params.pid, - // category: '10', uploadFiles: files, setUploadFiles: setFiles, } @@ -123,24 +123,42 @@ export default function Estimate({ params }) { event.stopPropagation() } - // 첨부파일 state에 넣기 + // 추가한 첨부파일 state에 넣기 useEffect(() => { - // console.log(files) - if (files.length > 0) { + if (isNotEmptyArray(files)) { files.map((row) => { setState({ fileList: row.data }) }) } else { - console.log('첨부파일 없음') setState({ fileList: [] }) } }, [files]) + //상세에서 내려온 첨부파일 set 만들기 + useEffect(() => { + if (isNotEmptyArray(state.fileList)) { + setOriginFiles(state.fileList) + } + }, [state?.fileList]) + + // 기존첨부파일 삭제 + const deleteOriginFile = async (objectNo, no) => { + const delParams = { + userId: session.userId, + objectNo: objectNo, + no: no, + } + await promisePost({ url: 'api/file/fileDelete', data: delParams }).then((res) => { + if (res.status === 204) { + setOriginFiles(originFiles.filter((file) => file.objectNo === objectNo && file.no !== no)) + } + }) + } + return (
{/* 물건번호, 견적서번호, 등록일, 변경일시 시작 */} - {/*
*/}
@@ -395,6 +413,23 @@ export default function Estimate({ params }) { {getMessage('estimate.detail.header.fileList2')} + +
+
    + {isNotEmptyArray(originFiles) && + originFiles.map((originFile) => { + return ( +
  • + + {originFile.faileName} + + +
  • + ) + })} +
+
+ @@ -444,7 +479,7 @@ export default function Estimate({ params }) { ) })}
- {/* 견적특이사항 선택한 내용?영역시작 */} + {/* 견적특이사항 선택한 내용 영역시작 */}
{specialNoteList.map((row) => { if (row.code === showContentCode) { @@ -575,7 +610,6 @@ export default function Estimate({ params }) {
{/* 기본정보끝 */} - {/* */}
) From 3e5e5963a42ec38462948cf3e3c2d21964f6d88c Mon Sep 17 00:00:00 2001 From: basssy Date: Thu, 7 Nov 2024 11:45:13 +0900 Subject: [PATCH 18/51] =?UTF-8?q?=EB=AC=BC=EA=B1=B4=EB=AA=A9=EB=A1=9D=20?= =?UTF-8?q?=EC=86=8C=EC=8A=A4=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/management/Stuff.jsx | 2 -- .../management/StuffSearchCondition.jsx | 16 +++++++--------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/src/components/management/Stuff.jsx b/src/components/management/Stuff.jsx index 8c97347d..bdd3e1d0 100644 --- a/src/components/management/Stuff.jsx +++ b/src/components/management/Stuff.jsx @@ -9,13 +9,11 @@ import { useRecoilValue, useRecoilState, useSetRecoilState, useResetRecoilState import { stuffSearchState } from '@/store/stuffAtom' import { queryStringFormatter, isEmptyArray } from '@/util/common-utils' import dayjs from 'dayjs' -import { isObjectNotEmpty } from '@/util/common-utils' import { convertNumberToPriceDecimal } from '@/util/common-utils' import { appMessageStore, globalLocaleStore } from '@/store/localeAtom' import KO from '@/locales/ko.json' import JA from '@/locales/ja.json' import QPagination from '../common/pagination/QPagination' -import { sessionStore } from '@/store/commonAtom' import { SessionContext } from '@/app/SessionProvider' export default function Stuff() { diff --git a/src/components/management/StuffSearchCondition.jsx b/src/components/management/StuffSearchCondition.jsx index 1d40b61a..9b76dca0 100644 --- a/src/components/management/StuffSearchCondition.jsx +++ b/src/components/management/StuffSearchCondition.jsx @@ -12,7 +12,6 @@ import { isEmptyArray } from '@/util/common-utils' import dayjs from 'dayjs' import Link from 'next/link' import SingleDatePicker from '../common/datepicker/SingleDatePicker' -import { sessionStore } from '@/store/commonAtom' import { useMessage } from '@/hooks/useMessage' import { isObjectNotEmpty } from '@/util/common-utils' @@ -20,7 +19,6 @@ import { SessionContext } from '@/app/SessionProvider' export default function StuffSearchCondition() { const { session } = useContext(SessionContext) - const sessionState = useRecoilValue(sessionStore) const setAppMessageState = useSetRecoilState(appMessageStore) const globalLocaleState = useRecoilValue(globalLocaleStore) const { getMessage } = useMessage() @@ -163,7 +161,7 @@ export default function StuffSearchCondition() { } else { if (session.storeLvl === '1') { //T01아닌 1차점일때 - url = `/api/object/saleStore/${session?.storeId}/list?firstFlg=1&userId=${sessionState?.userId}` + url = `/api/object/saleStore/${session?.storeId}/list?firstFlg=1&userId=${session?.userId}` } else { url = `/api/object/saleStore/${session?.storeId}/list?firstFlg=1&userId=${session?.userId}` } @@ -385,7 +383,7 @@ export default function StuffSearchCondition() { ref={objectNoRef} className="input-light" defaultValue={stuffSearch?.schObjectNo ? stuffSearch.schObjectNo : objectNo} - onChange={(e) => { + onChange={() => { setObjectNo(objectNoRef.current.value) }} onKeyUp={handleByOnKeyUp} @@ -400,7 +398,7 @@ export default function StuffSearchCondition() { ref={saleStoreNameRef} className="input-light" defaultValue={stuffSearch?.schSaleStoreName ? stuffSearch.schSaleStoreName : saleStoreName} - onChange={(e) => { + onChange={() => { setSaleStoreName(saleStoreNameRef.current.value) }} onKeyUp={handleByOnKeyUp} @@ -415,7 +413,7 @@ export default function StuffSearchCondition() { ref={addressRef} className="input-light" defaultValue={stuffSearch?.schAddress ? stuffSearch.schAddress : address} - onChange={(e) => { + onChange={() => { setAddress(addressRef.current.value) }} onKeyUp={handleByOnKeyUp} @@ -430,7 +428,7 @@ export default function StuffSearchCondition() { ref={dispCompanyNameRef} className="input-light" defaultValue={stuffSearch?.schDispCompanyName ? stuffSearch.schDispCompanyName : dispCompanyName} - onChange={(e) => { + onChange={() => { setDispCompanyName(dispCompanyNameRef.current.value) }} onKeyUp={handleByOnKeyUp} @@ -447,7 +445,7 @@ export default function StuffSearchCondition() { ref={objectNameRef} className="input-light" defaultValue={stuffSearch?.schObjectName ? stuffSearch.schObjectName : objectName} - onChange={(e) => { + onChange={() => { setobjectName(objectNameRef.current.value) }} onKeyUp={handleByOnKeyUp} @@ -462,7 +460,7 @@ export default function StuffSearchCondition() { className="input-light" ref={receiveUserRef} defaultValue={stuffSearch?.schReceiveUser ? stuffSearch.schReceiveUser : receiveUser} - onChange={(e) => { + onChange={() => { setReceiveUser(receiveUserRef.current.value) }} onKeyUp={handleByOnKeyUp} From d6041b43226de27b9015525dc1d5a1370b7fb41d Mon Sep 17 00:00:00 2001 From: basssy Date: Thu, 7 Nov 2024 13:08:50 +0900 Subject: [PATCH 19/51] =?UTF-8?q?=EB=AC=BC=EA=B1=B4=EB=AA=A9=EB=A1=9D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/management/Stuff.jsx | 4 +++- src/components/management/StuffSearchCondition.jsx | 6 ++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/components/management/Stuff.jsx b/src/components/management/Stuff.jsx index bdd3e1d0..58b1c002 100644 --- a/src/components/management/Stuff.jsx +++ b/src/components/management/Stuff.jsx @@ -190,7 +190,9 @@ export default function Stuff() { }) } - fetchData() + if (stuffSearch.schSelSaleStoreId !== '') { + fetchData() + } } else if (stuffSearchParams?.code === 'M') { const params = { saleStoreId: session?.storeId, diff --git a/src/components/management/StuffSearchCondition.jsx b/src/components/management/StuffSearchCondition.jsx index 9b76dca0..7bd8f456 100644 --- a/src/components/management/StuffSearchCondition.jsx +++ b/src/components/management/StuffSearchCondition.jsx @@ -321,6 +321,12 @@ export default function StuffSearchCondition() { useEffect(() => { setStartDate(stuffSearch?.schFromDt ? stuffSearch.schFromDt : dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD')) setEndDate(stuffSearch?.schToDt ? stuffSearch.schToDt : dayjs(new Date()).format('YYYY-MM-DD')) + setObjectNo(stuffSearch.schObjectNo ? stuffSearch.schObjectNo : objectNo) + setSaleStoreName(stuffSearch.schSaleStoreName ? stuffSearch.schSaleStoreName : saleStoreName) + setAddress(stuffSearch.schAddress ? stuffSearch.schAddress : address) + setobjectName(stuffSearch.schObjectName ? stuffSearch.schObjectName : objectName) + setDispCompanyName(stuffSearch.schDispCompanyName ? stuffSearch.schDispCompanyName : dispCompanyName) + setReceiveUser(stuffSearch.schReceiveUser ? stuffSearch.schReceiveUser : receiveUser) }, [stuffSearch]) useEffect(() => { From 78a6ba1ed79bf37dabc10831ade9054a7d1a730e Mon Sep 17 00:00:00 2001 From: Jaeyoung Lee Date: Thu, 7 Nov 2024 13:40:39 +0900 Subject: [PATCH 20/51] =?UTF-8?q?=ED=8E=B8=EB=A5=98=EC=A7=80=EB=B6=95=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Roof2.jsx | 2 +- src/components/fabric/QPolygon.js | 49 ++++++++++++++++++++------- src/hooks/useMode.js | 26 +++++++++----- src/util/qpolygon-utils.js | 56 +++++++++++++++++++++++++++++-- 4 files changed, 109 insertions(+), 24 deletions(-) diff --git a/src/components/Roof2.jsx b/src/components/Roof2.jsx index fad075bd..82ba40c1 100644 --- a/src/components/Roof2.jsx +++ b/src/components/Roof2.jsx @@ -431,7 +431,7 @@ export default function Roof2(props) { { x: 450, y: 850 }, ] - const polygon = new QPolygon(rectangleType2, { + const polygon = new QPolygon(type2, { fill: 'transparent', stroke: 'green', strokeWidth: 1, diff --git a/src/components/fabric/QPolygon.js b/src/components/fabric/QPolygon.js index 44cbfb37..8e450e77 100644 --- a/src/components/fabric/QPolygon.js +++ b/src/components/fabric/QPolygon.js @@ -2,7 +2,7 @@ import { fabric } from 'fabric' import { v4 as uuidv4 } from 'uuid' import { QLine } from '@/components/fabric/QLine' import { distanceBetweenPoints, findTopTwoIndexesByDistance, getDirectionByPoint, sortedPointLessEightPoint, sortedPoints } from '@/util/canvas-util' -import { calculateAngle, drawRidgeRoof, drawHippedRoof, inPolygon, toGeoJSON } from '@/util/qpolygon-utils' +import { calculateAngle, drawRidgeRoof, drawShedRoof, inPolygon, toGeoJSON } from '@/util/qpolygon-utils' import * as turf from '@turf/turf' import { LINE_TYPE } from '@/common/common' @@ -187,7 +187,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { const eavesType = [LINE_TYPE.WALLLINE.EAVES, LINE_TYPE.WALLLINE.HIPANDGABLE] const gableType = [LINE_TYPE.WALLLINE.GABLE, LINE_TYPE.WALLLINE.JERKINHEAD] - const isEaves = types.every((type) => eavesType.includes(type)) + // const isEaves = types.every((type) => eavesType.includes(type)) const gableOdd = types.filter((type, i) => i % 2 === 0) const gableEven = types.filter((type, i) => i % 2 === 1) const hasShed = types.includes(LINE_TYPE.WALLLINE.SHED) @@ -199,18 +199,41 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { ) { console.log('박공 지붕') } else if (hasShed) { - //편류지붕 - let shedIndex = 0 - types.forEach((type, i) => { - if (type === LINE_TYPE.WALLLINE.SHED) { - shedIndex = i - } + const sheds = this.lines.filter((line) => line.attributes !== undefined && line.attributes.type === LINE_TYPE.WALLLINE.SHED) + const areLinesParallel = function (line1, line2) { + const angle1 = calculateAngle(line1.startPoint, line1.endPoint) + const angle2 = calculateAngle(line2.startPoint, line2.endPoint) + return angle1 === angle2 + } + + let isShedRoof = true + sheds.forEach((shed, i) => { + isShedRoof = areLinesParallel(shed, sheds[(i + 1) % sheds.length]) }) - const shedOdd = types.filter((type, i) => i % 2 === shedIndex % 2).filter((type) => type !== LINE_TYPE.WALLLINE.SHED) - const shedEven = types.filter((type, i) => i % 2 !== shedIndex % 2) - types.forEach((type, i) => console.log(type, i, i % 2, shedIndex % 2, i % 2 === shedIndex % 2)) - if (shedOdd.every((type) => type === LINE_TYPE.WALLLINE.EAVES) && shedEven.every((type) => type === LINE_TYPE.WALLLINE.GABLE)) { - console.log('편류지붕') + if (isShedRoof) { + const eaves = this.lines + .filter((line) => line.attributes !== undefined && line.attributes.type === LINE_TYPE.WALLLINE.EAVES) + .filter((line) => { + const angle1 = calculateAngle(sheds[0].startPoint, sheds[0].endPoint) + const angle2 = calculateAngle(line.startPoint, line.endPoint) + if (Math.abs(angle1 - angle2) === 180) { + return line + } + }) + if (eaves.length > 0) { + const gables = this.lines.filter((line) => sheds.includes(line) === false && eaves.includes(line) === false) + const isGable = gables.every((line) => gableType.includes(line.attributes.type)) + console.log('isGable : ', isGable) + if (isGable) { + drawShedRoof(this.id, this.canvas) + } else { + drawRidgeRoof(this.id, this.canvas) + } + } else { + drawRidgeRoof(this.id, this.canvas) + } + } else { + drawRidgeRoof(this.id, this.canvas) } } else { drawRidgeRoof(this.id, this.canvas) diff --git a/src/hooks/useMode.js b/src/hooks/useMode.js index 486bc8e9..1b91fb7e 100644 --- a/src/hooks/useMode.js +++ b/src/hooks/useMode.js @@ -36,7 +36,7 @@ import { QPolygon } from '@/components/fabric/QPolygon' import offsetPolygon from '@/util/qpolygon-utils' import { isObjectNotEmpty } from '@/util/common-utils' import * as turf from '@turf/turf' -import { INPUT_TYPE, LINE_TYPE, Mode, POLYGON_TYPE } from '@/common/common' +import { INPUT_TYPE, Mode, POLYGON_TYPE } from '@/common/common' export function useMode() { const [mode, setMode] = useRecoilState(modeState) @@ -1515,9 +1515,17 @@ export function useMode() { pitch: 4, sleeve: true, } - /*if (index === 1 || index === 3) { + /*if (index === 1) { line.attributes = { - type: LINE_TYPE.WALLLINE.WALL, + type: LINE_TYPE.WALLLINE.SHED, + offset: 30, //출폭 + width: 30, //폭 + pitch: 4, //구배 + sleeve: true, //소매 + } + } else if (index === 5 || index === 3) { + line.attributes = { + type: LINE_TYPE.WALLLINE.EAVES, offset: 50, //출폭 width: 30, //폭 pitch: 4, //구배 @@ -1525,8 +1533,8 @@ export function useMode() { } } else { line.attributes = { - type: LINE_TYPE.WALLLINE.EAVES, - offset: 40, + type: LINE_TYPE.WALLLINE.GABLE, + offset: 20, width: 50, pitch: 4, sleeve: true, @@ -1750,8 +1758,13 @@ export function useMode() { roof.setWall(wall) roof.lines.forEach((line, index) => { + const lineLength = Math.sqrt( + Math.pow(Math.round(Math.abs(line.x1 - line.x2) * 10), 2) + Math.pow(Math.round(Math.abs(line.y1 - line.y2) * 10), 2), + ) line.attributes = { roofId: roof.id, + planeSize: lineLength, + actualSize: lineLength, wallLine: wall.lines[index].id, type: wall.lines[index].attributes.type, offset: wall.lines[index].attributes.offset, @@ -1770,9 +1783,6 @@ export function useMode() { line.attributes.currentRoof = roof.lines[index].id }) - console.log('drawRoofPolygon roof : ', roof) - console.log('drawRoofPolygon wall : ', wall) - setRoof(roof) setWall(wall) diff --git a/src/util/qpolygon-utils.js b/src/util/qpolygon-utils.js index e373df8d..a45fa6aa 100644 --- a/src/util/qpolygon-utils.js +++ b/src/util/qpolygon-utils.js @@ -1477,6 +1477,42 @@ function calculateAngleBetweenLines(line1, line2) { return (angleInRadians * 180) / Math.PI } +/** + * 한쪽흐름 지붕 + * @param roofId + * @param canvas + */ +export const drawShedRoof = (roofId, canvas) => { + const roof = canvas?.getObjects().find((object) => object.id === roofId) + const hasNonParallelLines = roof.lines.filter((line) => line.x1 !== line.x2 && line.y1 !== line.y2) + if (hasNonParallelLines.length > 0) { + alert('대각선이 존재합니다.') + return + } + + const sheds = roof.lines.filter((line) => line.attributes !== undefined && line.attributes.type === LINE_TYPE.WALLLINE.SHED) + const eaves = roof.lines.filter((line) => line.attributes !== undefined && line.attributes.type === LINE_TYPE.WALLLINE.EAVES) + const gables = roof.lines.filter((line) => line.attributes !== undefined && line.attributes.type === LINE_TYPE.WALLLINE.GABLE) + + console.log('gable', gables) + + let shedDegree = sheds[0].attributes.degree || 0 + const shedChon = sheds[0].attributes.pitch || 0 + + if (shedDegree === 0) { + shedDegree = getDegreeByChon(shedChon) + } + const getHeight = function (adjust, degree) { + return Math.tan(degree * (Math.PI / 180)) * adjust + } + + gables.forEach((gable) => { + const adjust = gable.attributes.planeSize + const height = getHeight(adjust, shedDegree) + gable.attributes.actualSize = Math.round(Math.sqrt(Math.pow(adjust, 2) + Math.pow(height, 2))) + }) +} + export const drawRidgeRoof = (roofId, canvas) => { const roof = canvas?.getObjects().find((object) => object.id === roofId) const hasNonParallelLines = roof.lines.filter((line) => line.x1 !== line.x2 && line.y1 !== line.y2) @@ -1904,8 +1940,6 @@ const drawHips = (roof, canvas) => { attributes: { roofId: roof.id, currentRoof: currentRoof.id, - planeSize: currentRoof.length, - actualSize: currentRoof.length, }, }) canvas.add(hip2) @@ -3505,8 +3539,13 @@ export const changeCurrentRoof = (currentRoof, canvas) => { newRoof.setWall(wall) newRoof.lines.forEach((line, index) => { + const lineLength = Math.sqrt( + Math.pow(Math.round(Math.abs(line.x1 - line.x2) * 10), 2) + Math.pow(Math.round(Math.abs(line.y1 - line.y2) * 10), 2), + ) line.attributes = { roofId: newRoof.id, + planeSize: lineLength, + actualSize: lineLength, wallLine: wall.lines[index].id, type: wall.lines[index].attributes.type, offset: wall.lines[index].attributes.offset, @@ -3561,6 +3600,19 @@ const reDrawPolygon = (polygon, canvas) => { line.attributes = l.attributes } }) + const lineLength = Math.sqrt( + Math.pow(Math.round(Math.abs(line.x1 - line.x2) * 10), 2) + Math.pow(Math.round(Math.abs(line.y1 - line.y2) * 10), 2), + ) + if (line.attributes !== undefined) { + line.attributes.planeSize = lineLength + line.attributes.actualSize = line + } else { + line.attributes = { + roofId: newPolygon.id, + planeSize: lineLength, + actualSize: lineLength, + } + } }) canvas?.add(newPolygon) From 16262f4c3eadb4726aaf0ad31a26df3392d85e3f Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Thu, 7 Nov 2024 14:08:49 +0900 Subject: [PATCH 21/51] =?UTF-8?q?children=20=EA=B2=80=EC=83=89=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/fabric/QPolygon.js | 12 ++++++++++-- src/util/canvas-util.js | 29 +++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/src/components/fabric/QPolygon.js b/src/components/fabric/QPolygon.js index 44cbfb37..d5746d5f 100644 --- a/src/components/fabric/QPolygon.js +++ b/src/components/fabric/QPolygon.js @@ -1,7 +1,14 @@ import { fabric } from 'fabric' import { v4 as uuidv4 } from 'uuid' import { QLine } from '@/components/fabric/QLine' -import { distanceBetweenPoints, findTopTwoIndexesByDistance, getDirectionByPoint, sortedPointLessEightPoint, sortedPoints } from '@/util/canvas-util' +import { + distanceBetweenPoints, + findTopTwoIndexesByDistance, + getAllRelatedObjects, + getDirectionByPoint, + sortedPointLessEightPoint, + sortedPoints, +} from '@/util/canvas-util' import { calculateAngle, drawRidgeRoof, drawHippedRoof, inPolygon, toGeoJSON } from '@/util/qpolygon-utils' import * as turf from '@turf/turf' import { LINE_TYPE } from '@/common/common' @@ -131,7 +138,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { }) this.on('removed', () => { - const children = this.canvas.getObjects().filter((obj) => obj.parentId === this.id) + const children = getAllRelatedObjects(this.id, this.canvas) children.forEach((child) => { this.canvas.remove(child) }) @@ -169,6 +176,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { offset: 0, }, parent: this, + parentId: this.id, direction: getDirectionByPoint(point, nextPoint), idx: i + 1, }) diff --git a/src/util/canvas-util.js b/src/util/canvas-util.js index 1a78f991..a78beb15 100644 --- a/src/util/canvas-util.js +++ b/src/util/canvas-util.js @@ -925,3 +925,32 @@ export function checkLineOrientation(line) { return 'diagonal' // 대각선 } } + +// 최상위 parentId를 통해 모든 하위 객체를 찾는 함수 +export const getAllRelatedObjects = (id, canvas) => { + const result = [] + const map = new Map() + + // Create a map of objects by their id + canvas.getObjects().forEach((obj) => { + map.set(obj.id, obj) + }) + + // Helper function to recursively find all related objects + function findRelatedObjects(id) { + const obj = map.get(id) + if (obj) { + result.push(obj) + canvas.getObjects().forEach((o) => { + if (o.parentId === id) { + findRelatedObjects(o.id) + } + }) + } + } + + // Start the search with the given parentId + findRelatedObjects(id) + + return result +} From bf8986b509f83a216fff118984509e290c04f14a Mon Sep 17 00:00:00 2001 From: Jaeyoung Lee Date: Thu, 7 Nov 2024 14:38:05 +0900 Subject: [PATCH 22/51] =?UTF-8?q?=EC=A7=80=EB=B6=95=20=EB=B3=80=EA=B2=BD?= =?UTF-8?q?=EC=8B=9C=20=EA=B8=B8=EC=9D=B4,=20innerlines=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC=20=EB=B6=80=EB=B6=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/util/qpolygon-utils.js | 212 +++++++++++++++++-------------------- 1 file changed, 98 insertions(+), 114 deletions(-) diff --git a/src/util/qpolygon-utils.js b/src/util/qpolygon-utils.js index e9d12a9b..16a73098 100644 --- a/src/util/qpolygon-utils.js +++ b/src/util/qpolygon-utils.js @@ -1807,6 +1807,9 @@ const drawRidge = (roof, canvas) => { attributes: { roofId: roof.id }, }, ) + ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 + ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 + canvas.add(ridge) roof.ridges.push(ridge) roof.innerLines.push(ridge) @@ -1847,6 +1850,8 @@ const drawRidge = (roof, canvas) => { roof.ridges = roof.ridges.filter((r) => !(ridge2.x1 === r.x1 && ridge2.y1 === r.y1 && ridge2.x2 === r.x2 && ridge2.y2 === r.y2)) roof.innerLines = roof.innerLines.filter((r) => !(ridge.x1 === r.x1 && ridge.y1 === r.y1 && ridge.x2 === r.x2 && ridge.y2 === r.y2)) roof.innerLines = roof.innerLines.filter((r) => !(ridge2.x1 === r.x1 && ridge2.y1 === r.y1 && ridge2.x2 === r.x2 && ridge2.y2 === r.y2)) + newRidge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 + newRidge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 canvas.add(newRidge) roof.ridges.push(newRidge) roof.innerLines.push(newRidge) @@ -1922,7 +1927,7 @@ const drawHips = (roof, canvas) => { stroke: 'red', strokeWidth: 1, name: LINE_TYPE.SUBLINE.HIP, - attributes: { roofId: roof.id, currentRoof: currentRoof.id }, + attributes: { roofId: roof.id, currentRoof: currentRoof.id, actualSize: 0 }, }) canvas.add(hip1) const hip1Base = ((Math.abs(hip1.x1 - hip1.x2) + Math.abs(hip1.y1 - hip1.y2)) / 2) * 10 @@ -1939,10 +1944,7 @@ const drawHips = (roof, canvas) => { stroke: 'red', strokeWidth: 1, name: LINE_TYPE.SUBLINE.HIP, - attributes: { - roofId: roof.id, - currentRoof: currentRoof.id, - }, + attributes: { roofId: roof.id, currentRoof: currentRoof.id, actualSize: 0 }, }) canvas.add(hip2) const hip2Base = ((Math.abs(hip2.x1 - hip2.x2) + Math.abs(hip2.y1 - hip2.y2)) / 2) * 10 @@ -2013,12 +2015,7 @@ const drawHips = (roof, canvas) => { stroke: 'red', strokeWidth: 1, name: LINE_TYPE.SUBLINE.HIP, - attributes: { - roofId: roof.id, - currentRoof: currentRoof.id, - planeSize: currentRoof.length, - actualSize: currentRoof.length, - }, + attributes: { roofId: roof.id, currentRoof: currentRoof.id, actualSize: 0 }, }) canvas.add(hip) const hipBase = ((Math.abs(hip.x1 - hip.x2) + Math.abs(hip.y1 - hip.y2)) / 2) * 10 @@ -2076,92 +2073,6 @@ const checkValley = (polygon, line1, line2) => { return isValley } -const getPointInPolygon = (polygon, point, isInclude = false) => { - let inside = false - let minX = Math.min(polygon[0].x, polygon[1].x, polygon[2].x, polygon[3].x), - maxX = Math.max(polygon[0].x, polygon[1].x, polygon[2].x, polygon[3].x), - minY = Math.min(polygon[0].y, polygon[1].y, polygon[2].y, polygon[3].y), - maxY = Math.max(polygon[0].y, polygon[1].y, polygon[2].y, polygon[3].y) - if (!isInclude && minX < point.x && point.x < maxX && minY < point.y && point.y < maxY) { - inside = true - } - if (isInclude && minX <= point.x && point.x <= maxX && minY <= point.y && point.y <= maxY) { - inside = true - } - return inside -} - -/** - * 라인과 마주하는 다른 라인과의 가장 가까운 거리를 구한다. - * @param polygon - * @param currentLine 현재 라인 - * @param dVector 현재 라인의 방향 - * @returns {*[]|null} - */ -const getAcrossLine = (polygon, currentLine, dVector) => { - let acrossLine - switch (dVector) { - case 45: - acrossLine = polygon.lines - .filter((line) => line.x1 > currentLine.x1 && line.y1 <= currentLine.y1) - .reduce((prev, current) => { - if (prev.length > 0) { - return Math.abs(currentLine.x1 - current.x1) < Math.abs(currentLine.x1 - prev.x1) ? current : prev - } else { - return current - } - }, []) - break - case 135: - acrossLine = polygon.lines - .filter((line) => line.x1 > currentLine.x1 && line.y1 >= currentLine.y1) - .reduce((prev, current) => { - if (prev.length > 0) { - return Math.abs(currentLine.x1 - current.x1) < Math.abs(currentLine.x1 - prev.x1) ? current : prev - } else { - return current - } - }, []) - break - case 225: - acrossLine = polygon.lines - .filter((line) => line.x1 < currentLine.x1 && line.y1 >= currentLine.y1) - .reduce((prev, current) => { - if (prev.length > 0) { - return Math.abs(currentLine.x1 - current.x1) < Math.abs(currentLine.x1 - prev.x1) ? current : prev - } else { - return current - } - }, []) - break - case 315: - acrossLine = polygon.lines - .filter((line) => line.x1 < currentLine.x1 && line.y1 <= currentLine.y1) - .reduce((prev, current) => { - if (prev.length > 0) { - return Math.abs(currentLine.x1 - current.x1) < Math.abs(currentLine.x1 - prev.x1) ? current : prev - } else { - return current - } - }, []) - break - } - return acrossLine -} - -/* - 추녀마루(hip) 중복방지를 위해 마루와 함께 그려진 추녀마루를 확인한다 - */ -const isAlreadyHip = (polygon, line) => { - let isAlreadyHip = false - polygon.hips.forEach((hip) => { - if (line.x1 === hip.x1 && line.y1 === hip.y1) { - isAlreadyHip = true - } - }) - return isAlreadyHip -} - /* 3개 이상 이어지지 않은 라인 포인트 계산 모임지붕에서 point는 3개 이상의 라인과 접해야 함. @@ -2252,6 +2163,8 @@ const connectLinePoint = (polygon) => { stroke: 'purple', strokeWidth: 1, }) + line.attributes.planeSize = Math.round(Math.sqrt(Math.pow(line.x1 - line.x2, 2) + Math.pow(line.y1 - line.y2, 2)) * 10) / 10 + line.attributes.actualSize = Math.round(Math.sqrt(Math.pow(line.x1 - line.x2, 2) + Math.pow(line.y1 - line.y2, 2)) * 10) / 10 polygon.canvas.add(line) polygon.innerLines.push(line) }) @@ -2308,6 +2221,8 @@ const connectLinePoint = (polygon) => { stroke: 'purple', strokeWidth: 1, }) + line.attributes.planeSize = Math.round(Math.sqrt(Math.pow(line.x1 - line.x2, 2) + Math.pow(line.y1 - line.y2, 2)) * 10) / 10 + line.attributes.actualSize = Math.round(Math.sqrt(Math.pow(line.x1 - line.x2, 2) + Math.pow(line.y1 - line.y2, 2)) * 10) / 10 polygon.canvas.add(line) polygon.innerLines.push(line) }) @@ -2612,6 +2527,8 @@ const changeEavesRoof = (currentRoof, canvas) => { hipX2 = midX - addHipX2 hipY2 = midY - addHipY2 } + ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 + ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 } hipLines.forEach((hip) => { @@ -2789,6 +2706,8 @@ const changeGableRoof = (currentRoof, canvas) => { }) currentRoof.attributes.ridgeCoordinate = { x1: ridge.x2, y1: ridge.y2 } } + ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 + ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 let hip1 = new QLine([currentRoof.x1, currentRoof.y1, midX, midY], { fontSize: roof.fontSize, @@ -2850,6 +2769,14 @@ const changeHipAndGableRoof = (currentRoof, canvas) => { if (wallLine.length > 0) { wallLine = wallLine[0] } + let prevRoof, nextRoof + roof.lines.forEach((r, index) => { + if (r.id === currentRoof.id) { + currentRoof = r + prevRoof = roof.lines[index === 0 ? roof.lines.length - 1 : index - 1] + nextRoof = roof.lines[index === roof.lines.length - 1 ? 0 : index + 1] + } + }) const midX = (currentRoof.x1 + currentRoof.x2) / 2 // 지붕의 X 중심 const midY = (currentRoof.y1 + currentRoof.y2) / 2 // 지붕의 Y 중심 @@ -2963,6 +2890,8 @@ const changeHipAndGableRoof = (currentRoof, canvas) => { }) currentRoof.attributes.ridgeCoordinate = { x1: ridge.x2, y1: ridge.y2 } } + ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 + ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 } const hip1 = new QLine([currentRoof.x1, currentRoof.y1, midX + hipX2, midY + hipY2], { @@ -2973,10 +2902,15 @@ const changeHipAndGableRoof = (currentRoof, canvas) => { attributes: { roofId: roof.id, currentRoof: currentRoof.id, - planeSize: currentRoof.length, - actualSize: currentRoof.length, }, }) + const prevDegree = prevRoof.attributes.pitch > 0 ? getDegreeByChon(prevRoof.attributes.pitch) : prevRoof.attributes.degree + const nextDegree = nextRoof.attributes.pitch > 0 ? getDegreeByChon(nextRoof.attributes.pitch) : nextRoof.attributes.degree + + const hip1Base = ((Math.abs(hip1.x1 - hip1.x2) + Math.abs(hip1.y1 - hip1.y2)) / 2) * 10 + const hip1Height = Math.round(hip1Base / Math.tan(((90 - prevDegree) * Math.PI) / 180)) + hip1.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip1.x1 - hip1.x2, 2) + Math.pow(hip1.y1 - hip1.y2, 2))) * 10 + hip1.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip1.attributes.planeSize, 2) + Math.pow(hip1Height, 2))) canvas?.add(hip1) roof.innerLines.push(hip1) @@ -2992,6 +2926,10 @@ const changeHipAndGableRoof = (currentRoof, canvas) => { actualSize: currentRoof.length, }, }) + const hip2Base = ((Math.abs(hip2.x1 - hip2.x2) + Math.abs(hip2.y1 - hip2.y2)) / 2) * 10 + const hip2Height = Math.round(hip2Base / Math.tan(((90 - nextDegree) * Math.PI) / 180)) + hip2.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip2.x1 - hip2.x2, 2) + Math.pow(hip2.y1 - hip2.y2, 2))) * 10 + hip2.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip2.attributes.planeSize, 2) + Math.pow(hip2Height, 2))) canvas?.add(hip2) roof.innerLines.push(hip2) @@ -3010,7 +2948,7 @@ const changeHipAndGableRoof = (currentRoof, canvas) => { }) }) - hipLines.forEach((hip) => { + hipLines.forEach((hip, i) => { const gableLine = new QLine([hip.x2, hip.y2, currentRoof.attributes.ridgeCoordinate.x1, currentRoof.attributes.ridgeCoordinate.y1], { fontSize: roof.fontSize, stroke: 'red', @@ -3019,10 +2957,15 @@ const changeHipAndGableRoof = (currentRoof, canvas) => { attributes: { roofId: roof.id, currentRoof: currentRoof.id, - planeSize: currentRoof.length, - actualSize: currentRoof.length, + actualSize: 0, }, }) + const gableDegree = i === 0 ? prevDegree : nextDegree + const gableBase = ((Math.abs(gableLine.x1 - gableLine.x2) + Math.abs(gableLine.y1 - gableLine.y2)) / 2) * 10 + const gableHeight = Math.round(gableBase / Math.tan(((90 - gableDegree) * Math.PI) / 180)) + gableLine.attributes.planeSize = + Math.round(Math.sqrt(Math.pow(gableLine.x1 - gableLine.x2, 2) + Math.pow(gableLine.y1 - gableLine.y2, 2))) * 10 + gableLine.attributes.actualSize = Math.round(Math.sqrt(Math.pow(gableLine.attributes.planeSize, 2) + Math.pow(gableHeight, 2))) canvas?.add(gableLine) roof.innerLines.push(gableLine) }) @@ -3052,6 +2995,18 @@ const changeJerkInHeadRoof = (currentRoof, canvas) => { wallLine = wallLine[0] } + let prevRoof, nextRoof + roof.lines.forEach((r, index) => { + if (r.id === currentRoof.id) { + currentRoof = r + prevRoof = roof.lines[index === 0 ? roof.lines.length - 1 : index - 1] + nextRoof = roof.lines[index === roof.lines.length - 1 ? 0 : index + 1] + } + }) + + const prevDegree = prevRoof.attributes.pitch > 0 ? getDegreeByChon(prevRoof.attributes.pitch) : prevRoof.attributes.degree + const nextDegree = nextRoof.attributes.pitch > 0 ? getDegreeByChon(nextRoof.attributes.pitch) : nextRoof.attributes.degree + const midX = (currentRoof.x1 + currentRoof.x2) / 2 // 지붕의 X 중심 const midY = (currentRoof.y1 + currentRoof.y2) / 2 // 지붕의 Y 중심 const midWallX = (wallLine.x1 + wallLine.x2) / 2 // 벽의 X 중심 @@ -3173,6 +3128,8 @@ const changeJerkInHeadRoof = (currentRoof, canvas) => { hipX2 = midX - xWidth hipY2 = midY - yWidth } + ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 + ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 } let hipX1 = (Math.sign(currentRoof.x1 - midX) * currentRoof.attributes.width) / 2 @@ -3186,10 +3143,14 @@ const changeJerkInHeadRoof = (currentRoof, canvas) => { attributes: { roofId: roof.id, currentRoofId: currentRoof.id, - planeSize: currentRoof.length, - actualSize: currentRoof.length, + actualSize: 0, }, }) + const gableDegree = currentRoof.attributes.degree > 0 ? currentRoof.attributes.degree : getDegreeByChon(currentRoof.attributes.pitch) + const gable1Base = ((Math.abs(gable1.x1 - gable1.x2) + Math.abs(gable1.y1 - gable1.y2)) / 2) * 10 + const gable1Height = Math.round(gable1Base / Math.tan(((90 - gableDegree) * Math.PI) / 180)) + gable1.attributes.planeSize = Math.round(Math.sqrt(Math.pow(gable1.x1 - gable1.x2, 2) + Math.pow(gable1.y1 - gable1.y2, 2))) * 10 + gable1.attributes.actualSize = Math.round(Math.sqrt(Math.pow(gable1.attributes.planeSize, 2) + Math.pow(gable1Height, 2))) canvas?.add(gable1) roof.innerLines.push(gable1) @@ -3204,10 +3165,13 @@ const changeJerkInHeadRoof = (currentRoof, canvas) => { attributes: { roofId: roof.id, currentRoofId: currentRoof.id, - planeSize: currentRoof.length, - actualSize: currentRoof.length, + actualSize: 0, }, }) + const gable2Base = ((Math.abs(gable2.x1 - gable2.x2) + Math.abs(gable2.y1 - gable2.y2)) / 2) * 10 + const gable2Height = Math.round(gable2Base / Math.tan(((90 - gableDegree) * Math.PI) / 180)) + gable2.attributes.planeSize = Math.round(Math.sqrt(Math.pow(gable2.x1 - gable2.x2, 2) + Math.pow(gable2.y1 - gable2.y2, 2))) * 10 + gable2.attributes.actualSize = Math.round(Math.sqrt(Math.pow(gable2.attributes.planeSize, 2) + Math.pow(gable2Height, 2))) canvas?.add(gable2) roof.innerLines.push(gable2) @@ -3219,10 +3183,11 @@ const changeJerkInHeadRoof = (currentRoof, canvas) => { attributes: { roofId: roof.id, currentRoofId: currentRoof.id, - planeSize: currentRoof.length, - actualSize: currentRoof.length, + actualSize: 0, }, }) + gable3.attributes.planeSize = Math.round(Math.sqrt(Math.pow(gable3.x1 - gable3.x2, 2) + Math.pow(gable3.y1 - gable3.y2, 2))) * 10 + gable3.attributes.actualSize = Math.round(Math.sqrt(Math.pow(gable3.x1 - gable3.x2, 2) + Math.pow(gable3.y1 - gable3.y2, 2))) * 10 canvas?.add(gable3) roof.innerLines.push(gable3) @@ -3234,10 +3199,13 @@ const changeJerkInHeadRoof = (currentRoof, canvas) => { attributes: { roofId: roof.id, currentRoofId: currentRoof.id, - planeSize: currentRoof.length, - actualSize: currentRoof.length, + actualSize: 0, }, }) + const hip1Base = ((Math.abs(hip1.x1 - hip1.x2) + Math.abs(hip1.y1 - hip1.y2)) / 2) * 10 + const hip1Height = Math.round(hip1Base / Math.tan(((90 - prevDegree) * Math.PI) / 180)) + hip1.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip1.x1 - hip1.x2, 2) + Math.pow(hip1.y1 - hip1.y2, 2))) * 10 + hip1.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip1.attributes.planeSize, 2) + Math.pow(hip1Height, 2))) canvas?.add(hip1) roof.innerLines.push(hip1) @@ -3249,10 +3217,13 @@ const changeJerkInHeadRoof = (currentRoof, canvas) => { attributes: { roofId: roof.id, currentRoofId: currentRoof.id, - planeSize: currentRoof.length, - actualSize: currentRoof.length, + actualSize: 0, }, }) + const hip2Base = ((Math.abs(hip2.x1 - hip2.x2) + Math.abs(hip2.y1 - hip2.y2)) / 2) * 10 + const hip2Height = Math.round(hip2Base / Math.tan(((90 - nextDegree) * Math.PI) / 180)) + hip2.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip2.x1 - hip2.x2, 2) + Math.pow(hip2.y1 - hip2.y2, 2))) * 10 + hip2.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip2.attributes.planeSize, 2) + Math.pow(hip2Height, 2))) canvas?.add(hip2) roof.innerLines.push(hip2) } @@ -3348,6 +3319,9 @@ const changeWallRoof = (currentRoof, canvas) => { canvas?.remove(line) }) + const prevDegree = prevRoof.attributes.pitch > 0 ? getDegreeByChon(prevRoof.attributes.pitch) : prevRoof.attributes.degree + const nextDegree = nextRoof.attributes.pitch > 0 ? getDegreeByChon(nextRoof.attributes.pitch) : nextRoof.attributes.degree + if (currentRoof.attributes.sleeve && currentRoof.attributes.width > 0 && prevRoof.attributes.offset > 0 && nextRoof.attributes.offset > 0) { const prevSignX = Math.sign(prevRoof.x1 - prevRoof.x2) const prevSignY = Math.sign(prevRoof.y1 - prevRoof.y2) @@ -3453,6 +3427,8 @@ const changeWallRoof = (currentRoof, canvas) => { y2: ridge.y2 - diffY, }) } + ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 + ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 let hip1 = new QLine([currentRoof.x1, currentRoof.y1, wallMidX, wallMidY], { fontSize: roof.fontSize, @@ -3462,10 +3438,14 @@ const changeWallRoof = (currentRoof, canvas) => { attributes: { roofId: roof.id, currentRoofId: currentRoof.id, - planeSize: currentRoof.length, - actualSize: currentRoof.length, + actualSize: 0, }, }) + const hip1Base = ((Math.abs(hip1.x1 - hip1.x2) + Math.abs(hip1.y1 - hip1.y2)) / 2) * 10 + const hip1Height = Math.round(hip1Base / Math.tan(((90 - prevDegree) * Math.PI) / 180)) + hip1.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip1.x1 - hip1.x2, 2) + Math.pow(hip1.y1 - hip1.y2, 2))) * 10 + hip1.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip1.attributes.planeSize, 2) + Math.pow(hip1Height, 2))) + let hip2 = new QLine([currentRoof.x2, currentRoof.y2, wallMidX, wallMidY], { fontSize: roof.fontSize, stroke: 'red', @@ -3478,6 +3458,10 @@ const changeWallRoof = (currentRoof, canvas) => { actualSize: currentRoof.length, }, }) + const hip2Base = ((Math.abs(hip2.x1 - hip2.x2) + Math.abs(hip2.y1 - hip2.y2)) / 2) * 10 + const hip2Height = Math.round(hip2Base / Math.tan(((90 - nextDegree) * Math.PI) / 180)) + hip2.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip2.x1 - hip2.x2, 2) + Math.pow(hip2.y1 - hip2.y2, 2))) * 10 + hip2.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip2.attributes.planeSize, 2) + Math.pow(hip2Height, 2))) canvas?.add(hip1) canvas?.add(hip2) roof.innerLines.push(hip1) From 7f1a2f54f7e90740900fcf2411286b8e24f7566d Mon Sep 17 00:00:00 2001 From: Jaeyoung Lee Date: Thu, 7 Nov 2024 14:49:24 +0900 Subject: [PATCH 23/51] =?UTF-8?q?import=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/fabric/QPolygon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/fabric/QPolygon.js b/src/components/fabric/QPolygon.js index f5e7eaae..339c9203 100644 --- a/src/components/fabric/QPolygon.js +++ b/src/components/fabric/QPolygon.js @@ -9,7 +9,7 @@ import { sortedPointLessEightPoint, sortedPoints, } from '@/util/canvas-util' -import { calculateAngle, drawRidgeRoof, inPolygon, toGeoJSON } from '@/util/qpolygon-utils' +import { calculateAngle, drawRidgeRoof, drawShedRoof, inPolygon, toGeoJSON } from '@/util/qpolygon-utils' import * as turf from '@turf/turf' import { LINE_TYPE } from '@/common/common' From dcd364bca07d8595987c86da31e4c3108e08785b Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Thu, 7 Nov 2024 16:49:05 +0900 Subject: [PATCH 24/51] =?UTF-8?q?splitPolygonWithLines=20usePolygon?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EC=88=98=EC=A0=95=20=EB=B0=A9=ED=96=A5=20?= =?UTF-8?q?index=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/common/common.js | 2 + .../roofcover/useRoofAllocationSetting.js | 3 +- src/hooks/useCanvasEvent.js | 12 +- src/hooks/usePolygon.js | 335 +++++++++++++++++- src/util/qpolygon-utils.js | 242 +------------ 5 files changed, 338 insertions(+), 256 deletions(-) diff --git a/src/common/common.js b/src/common/common.js index cf60295b..d0016af1 100644 --- a/src/common/common.js +++ b/src/common/common.js @@ -159,6 +159,8 @@ export const SAVE_KEY = [ 'groupName', 'lineDirection', 'groupId', + 'planeSize', + 'actualSize', ] export const OBJECT_PROTOTYPE = [fabric.Line.prototype, fabric.Polygon.prototype, fabric.Triangle.prototype] diff --git a/src/hooks/roofcover/useRoofAllocationSetting.js b/src/hooks/roofcover/useRoofAllocationSetting.js index c229549e..921e737a 100644 --- a/src/hooks/roofcover/useRoofAllocationSetting.js +++ b/src/hooks/roofcover/useRoofAllocationSetting.js @@ -2,7 +2,6 @@ import { useRecoilValue } from 'recoil' import { canvasState } from '@/store/canvasAtom' import { useEffect, useState } from 'react' import { setSurfaceShapePattern } from '@/util/canvas-util' -import { splitPolygonWithLines } from '@/util/qpolygon-utils' import { useSwal } from '@/hooks/useSwal' import { usePolygon } from '@/hooks/usePolygon' import { roofDisplaySelector } from '@/store/settingAtom' @@ -13,7 +12,7 @@ import { POLYGON_TYPE } from '@/common/common' export function useRoofAllocationSetting(id) { const canvas = useRecoilValue(canvasState) const roofDisplay = useRecoilValue(roofDisplaySelector) - const { drawDirectionArrow } = usePolygon() + const { drawDirectionArrow, addLengthText, splitPolygonWithLines } = usePolygon() const { closePopup } = usePopup() const { swalFire } = useSwal() diff --git a/src/hooks/useCanvasEvent.js b/src/hooks/useCanvasEvent.js index 9b25eedd..42266c8a 100644 --- a/src/hooks/useCanvasEvent.js +++ b/src/hooks/useCanvasEvent.js @@ -1,7 +1,7 @@ import { useEffect, useState } from 'react' import { useRecoilState, useRecoilValue } from 'recoil' import { v4 as uuidv4 } from 'uuid' -import { canvasSizeState, canvasState, canvasZoomState, currentObjectState, fontFamilyState, fontSizeState } from '@/store/canvasAtom' +import { canvasSizeState, canvasState, canvasZoomState, currentObjectState } from '@/store/canvasAtom' import { QPolygon } from '@/components/fabric/QPolygon' import { usePlan } from '@/hooks/usePlan' import { fontSelector } from '@/store/fontAtom' @@ -12,8 +12,6 @@ export function useCanvasEvent() { const [canvasForEvent, setCanvasForEvent] = useState(null) const [currentObject, setCurrentObject] = useRecoilState(currentObjectState) const canvasSize = useRecoilValue(canvasSizeState) - const fontSize = useRecoilValue(fontSizeState) - const fontFamily = useRecoilValue(fontFamilyState) const [canvasZoom, setCanvasZoom] = useRecoilState(canvasZoomState) const lengthTextOption = useRecoilValue(fontSelector('lengthText')) const { modifiedPlanFlag, setModifiedPlanFlag } = usePlan() @@ -211,7 +209,7 @@ export function useCanvasEvent() { setCurrentObject(target) const { selected } = e - if (selected.length > 0) { + if (selected?.length > 0) { selected.forEach((obj) => { if (obj.type === 'QPolygon') { obj.set({ stroke: 'red' }) @@ -224,7 +222,7 @@ export function useCanvasEvent() { setCurrentObject(null) const { deselected } = e - if (deselected.length > 0) { + if (deselected?.length > 0) { deselected.forEach((obj) => { if (obj.type === 'QPolygon') { obj.set({ stroke: 'black' }) @@ -238,7 +236,7 @@ export function useCanvasEvent() { setCurrentObject(target) const { selected, deselected } = e - if (deselected.length > 0) { + if (deselected?.length > 0) { deselected.forEach((obj) => { if (obj.type === 'QPolygon') { obj.set({ stroke: 'black' }) @@ -246,7 +244,7 @@ export function useCanvasEvent() { }) } - if (selected.length > 0) { + if (selected?.length > 0) { selected.forEach((obj) => { if (obj.type === 'QPolygon') { obj.set({ stroke: 'red' }) diff --git a/src/hooks/usePolygon.js b/src/hooks/usePolygon.js index 5a7d3062..9ea8b3b7 100644 --- a/src/hooks/usePolygon.js +++ b/src/hooks/usePolygon.js @@ -1,11 +1,13 @@ import { ANGLE_TYPE, canvasState, currentAngleTypeSelector, fontFamilyState, fontSizeState, pitchTextSelector } from '@/store/canvasAtom' import { useRecoilValue } from 'recoil' import { fabric } from 'fabric' -import { getDegreeByChon, getDirectionByPoint } from '@/util/canvas-util' +import { getDegreeByChon, getDirectionByPoint, isPointOnLine } from '@/util/canvas-util' import { QPolygon } from '@/components/fabric/QPolygon' -import { isSamePoint } from '@/util/qpolygon-utils' +import { isSamePoint, removeDuplicatePolygons } from '@/util/qpolygon-utils' import { flowDisplaySelector } from '@/store/settingAtom' import { fontSelector } from '@/store/fontAtom' +import { QLine } from '@/components/fabric/QLine' +import { POLYGON_TYPE } from '@/common/common' export const usePolygon = () => { const canvas = useRecoilValue(canvasState) @@ -25,6 +27,7 @@ export const usePolygon = () => { }) canvas?.add(polygon) + addLengthText(polygon) return polygon } @@ -40,7 +43,64 @@ export const usePolygon = () => { } const addLengthText = (polygon) => { - const points = polygon.get('points') + const lengthTexts = canvas.getObjects().filter((obj) => obj.name === 'lengthText' && obj.parentId === polygon.id) + lengthTexts.forEach((text) => { + canvas.remove(text) + }) + const lines = polygon.lines + + lines.forEach((line, i) => { + const length = line.getLength() + const { planeSize, actualSize } = line.attributes + const scaleX = line.scaleX + const scaleY = line.scaleY + const x1 = line.left + const y1 = line.top + const x2 = line.left + line.width * scaleX + const y2 = line.top + line.height * scaleY + + let left, top + + if (line.direction === 'left' || line.direction === 'right') { + left = (x1 + x2) / 2 + top = (y1 + y2) / 2 + 10 + } else if (line.direction === 'top' || line.direction === 'bottom') { + left = (x1 + x2) / 2 + 10 + top = (y1 + y2) / 2 + } + + const minX = line.left + const maxX = line.left + line.width + const minY = line.top + const maxY = line.top + line.length + const degree = (Math.atan2(y2 - y1, x2 - x1) * 180) / Math.PI + + const text = new fabric.Textbox(actualSize ? actualSize.toString() : planeSize ? planeSize.toString() : length.toString(), { + left: left, + top: top, + fontSize: lengthTextFontOptions.fontSize.value, + minX, + maxX, + minY, + maxY, + parentDirection: line.direction, + parentDegree: degree, + parentId: polygon.id, + planeSize, + actualSize, + editable: false, + selectable: true, + lockRotation: true, + lockScalingX: true, + lockScalingY: true, + parent: polygon, + name: 'lengthText', + }) + + canvas.add(text) + }) + + /*const points = polygon.get('points') points.forEach((start, i) => { const end = points[(i + 1) % points.length] const dx = end.x - start.x @@ -71,12 +131,12 @@ export const usePolygon = () => { lockScalingY: true, idx: i, name: 'lengthText', - parent: this, + parent: polygon, }) // this.texts.push(text) canvas.add(text) - }) + })*/ canvas.renderAll() } @@ -409,7 +469,8 @@ export const usePolygon = () => { const addTextByArrows = (arrows, txt, canvas) => { arrows.forEach((arrow, index) => { - const textStr = `${txt}${index + 1} (${currentAngleType === ANGLE_TYPE.SLOPE ? arrow.pitch : getDegreeByChon(arrow.pitch)}${pitchText})` + // const textStr = `${txt}${index + 1} (${currentAngleType === ANGLE_TYPE.SLOPE ? arrow.pitch : getDegreeByChon(arrow.pitch)}${pitchText})` + const textStr = `${txt} (${currentAngleType === ANGLE_TYPE.SLOPE ? arrow.pitch : getDegreeByChon(arrow.pitch)}${pitchText})` const text = new fabric.Text(`${textStr}`, { fontSize: flowFontOptions.fontSize.value, @@ -432,10 +493,272 @@ export const usePolygon = () => { }) } + const splitPolygonWithLines = (polygon) => { + polygon.set({ visible: false }) + let innerLines = [...polygon.innerLines] + let polygonLines = [...polygon.lines] + const roofs = [] + + let delIndexs = [] + let newLines = [] + + polygonLines.forEach((line, index) => { + line.tempIndex = index + innerLines.forEach((innerLine) => { + let newLine1, newLine2 + if (isPointOnLine(line, innerLine.startPoint)) { + // 해당 line을 startPoint로 나눈 line2개를 canvas에 추가 하고 기존 line을 제거한다. + newLine1 = new QLine([line.x1, line.y1, innerLine.startPoint.x, innerLine.startPoint.y], { + fontSize: polygon.fontSize, + stroke: 'black', + strokeWidth: 3, + }) + + newLine2 = new QLine([innerLine.startPoint.x, innerLine.startPoint.y, line.x2, line.y2], { + fontSize: polygon.fontSize, + stroke: 'black', + strokeWidth: 3, + }) + delIndexs.push(polygonLines.indexOf(line)) + canvas.remove(polygonLines[polygonLines.indexOf(line)]) + if (newLine1.length / 10 > 10) { + newLines.push(newLine1) + } + if (newLine2.length / 10 > 10) { + newLines.push(newLine2) + } + } + if (isPointOnLine(line, innerLine.endPoint)) { + newLine1 = new QLine([line.x1, line.y1, innerLine.endPoint.x, innerLine.endPoint.y], { + fontSize: polygon.fontSize, + stroke: 'black', + strokeWidth: 3, + }) + + newLine2 = new QLine([innerLine.endPoint.x, innerLine.endPoint.y, line.x2, line.y2], { + fontSize: polygon.fontSize, + stroke: 'black', + strokeWidth: 3, + }) + delIndexs.push(polygonLines.indexOf(line)) + canvas.remove(polygonLines[polygonLines.indexOf(line)]) + if (newLine1.length / 10 > 10) { + newLines.push(newLine1) + } + if (newLine2.length / 10 > 10) { + newLines.push(newLine2) + } + } + }) + }) + polygonLines = polygonLines.filter((line) => !delIndexs.includes(line.tempIndex)) + polygonLines = [...polygonLines, ...newLines] + + const allLines = [...polygonLines, ...innerLines] + + /** + * 왼쪽 상단을 startPoint로 전부 변경 + */ + allLines.forEach((line) => { + let startPoint // 시작점 + let endPoint // 끝점 + if (line.x1 < line.x2) { + startPoint = { x: line.x1, y: line.y1 } + endPoint = { x: line.x2, y: line.y2 } + } else if (line.x1 > line.x2) { + startPoint = { x: line.x2, y: line.y2 } + endPoint = { x: line.x1, y: line.y1 } + } else { + if (line.y1 < line.y2) { + startPoint = { x: line.x1, y: line.y1 } + endPoint = { x: line.x2, y: line.y2 } + } else { + startPoint = { x: line.x2, y: line.y2 } + endPoint = { x: line.x1, y: line.y1 } + } + } + + line.startPoint = startPoint + line.endPoint = endPoint + }) + + polygonLines.forEach((line) => { + const startPoint = line.startPoint // 시작점 + let arrivalPoint = line.endPoint // 도착점 + + let currentPoint = startPoint + const roofPoints = [startPoint] + + const startLine = line + const visitPoints = [startPoint] + const visitLines = [startLine] + let cnt = 0 + + while (!isSamePoint(currentPoint, arrivalPoint)) { + let nextLines = allLines.filter( + (line2) => + (isSamePoint(line2.startPoint, currentPoint) || isSamePoint(line2.endPoint, currentPoint)) && + line !== line2 && + innerLines.includes(line2) && + !visitLines.includes(line2), + ) + + if (nextLines.length === 0) { + nextLines = allLines.filter( + (line2) => + (isSamePoint(line2.startPoint, currentPoint) || isSamePoint(line2.endPoint, currentPoint)) && + line !== line2 && + !visitLines.includes(line2), + ) + } + + if (!nextLines) { + break + } + + let comparisonPoints = [] + + nextLines.forEach((nextLine) => { + if (isSamePoint(nextLine.startPoint, currentPoint)) { + comparisonPoints.push(nextLine.endPoint) + } else { + comparisonPoints.push(nextLine.startPoint) + } + }) + + comparisonPoints = comparisonPoints.filter((point) => !visitPoints.some((visitPoint) => isSamePoint(visitPoint, point))) + comparisonPoints = comparisonPoints.filter((point) => !isSamePoint(point, currentPoint)) + + const minDistancePoint = comparisonPoints.reduce((prev, current) => { + const prevDistance = Math.sqrt(Math.pow(prev.x - arrivalPoint.x, 2) + Math.pow(prev.y - arrivalPoint.y, 2)) + const currentDistance = Math.sqrt(Math.pow(current.x - arrivalPoint.x, 2) + Math.pow(current.y - arrivalPoint.y, 2)) + + return prevDistance < currentDistance ? prev : current + }, comparisonPoints[0]) + + nextLines.forEach((nextLine) => { + if (isSamePoint(nextLine.startPoint, minDistancePoint) || isSamePoint(nextLine.endPoint, minDistancePoint)) { + visitLines.push(nextLine) + } + }) + + currentPoint = { ...minDistancePoint } + roofPoints.push(currentPoint) + cnt++ + if (cnt > 100) { + throw new Error('무한루프') + } + } + roofs.push(roofPoints) + }) + + const newRoofs = removeDuplicatePolygons(roofs) + + newRoofs.forEach((roofPoint, index) => { + let defense, pitch + const polygonLines = [...polygon.lines] + + let representLines = [] + let representLine + + // 지붕을 그리면서 기존 polygon의 line중 연결된 line을 찾는다. + polygonLines.forEach((line) => { + let startFlag = false + let endFlag = false + const startPoint = line.startPoint + const endPoint = line.endPoint + roofPoint.forEach((point, index) => { + if (isSamePoint(point, startPoint)) { + startFlag = true + } + if (isSamePoint(point, endPoint)) { + endFlag = true + } + }) + + if (startFlag && endFlag) { + if (!representLines.includes(line)) { + representLines.push(line) + } + } + }) + + // representLines중 가장 긴 line을 찾는다. + representLines.forEach((line) => { + if (!representLine) { + representLine = line + } else { + if (representLine.length < line.length) { + representLine = line + } + } + }) + + const direction = newRoofs.length === 1 ? polygon.direction : representLine.direction + const polygonDirection = polygon.direction + + switch (direction) { + case 'top': + defense = 'east' + break + case 'right': + defense = 'south' + break + case 'bottom': + defense = 'west' + break + case 'left': + defense = 'north' + break + } + pitch = polygon.lines[index].attributes?.pitch ?? 0 + + const roof = new QPolygon(roofPoint, { + fontSize: polygon.fontSize, + stroke: 'black', + fill: 'transparent', + strokeWidth: 3, + name: POLYGON_TYPE.ROOF, + originX: 'center', + originY: 'center', + selectable: true, + defense: defense, + direction: newRoofs.length === 1 ? polygonDirection : defense, + pitch: pitch, + }) + + //allLines중 생성된 roof와 관련있는 line을 찾는다. + + roof.lines = [...polygon.lines, ...polygon.innerLines].filter((line) => { + let startFlag = false + let endFlag = false + const startPoint = line.startPoint + const endPoint = line.endPoint + roofPoint.forEach((point, index) => { + if (isSamePoint(point, startPoint)) { + startFlag = true + } + if (isSamePoint(point, endPoint)) { + endFlag = true + } + }) + + return startFlag && endFlag + }) + + canvas.add(roof) + addLengthText(roof) + canvas.remove(polygon) + canvas.renderAll() + }) + } + return { addPolygon, addPolygonByLines, removePolygon, drawDirectionArrow, + addLengthText, + splitPolygonWithLines, } } diff --git a/src/util/qpolygon-utils.js b/src/util/qpolygon-utils.js index 16a73098..66c1b509 100644 --- a/src/util/qpolygon-utils.js +++ b/src/util/qpolygon-utils.js @@ -1177,246 +1177,6 @@ export default function offsetPolygon(vertices, offset) { polygon.canvas.renderAll() }) }*/ -export const splitPolygonWithLines = (polygon) => { - const canvas = polygon.canvas - polygon.set({ visible: false }) - let innerLines = [...polygon.innerLines] - let polygonLines = [...polygon.lines] - const roofs = [] - - let delIndexs = [] - let newLines = [] - - polygonLines.forEach((line, index) => { - line.tempIndex = index - innerLines.forEach((innerLine) => { - let newLine1, newLine2 - if (isPointOnLine(line, innerLine.startPoint)) { - // 해당 line을 startPoint로 나눈 line2개를 canvas에 추가 하고 기존 line을 제거한다. - newLine1 = new QLine([line.x1, line.y1, innerLine.startPoint.x, innerLine.startPoint.y], { - fontSize: polygon.fontSize, - stroke: 'black', - strokeWidth: 3, - }) - - newLine2 = new QLine([innerLine.startPoint.x, innerLine.startPoint.y, line.x2, line.y2], { - fontSize: polygon.fontSize, - stroke: 'black', - strokeWidth: 3, - }) - delIndexs.push(polygonLines.indexOf(line)) - canvas.remove(polygonLines[polygonLines.indexOf(line)]) - if (newLine1.length / 10 > 10) { - newLines.push(newLine1) - } - if (newLine2.length / 10 > 10) { - newLines.push(newLine2) - } - } - if (isPointOnLine(line, innerLine.endPoint)) { - newLine1 = new QLine([line.x1, line.y1, innerLine.endPoint.x, innerLine.endPoint.y], { - fontSize: polygon.fontSize, - stroke: 'black', - strokeWidth: 3, - }) - - newLine2 = new QLine([innerLine.endPoint.x, innerLine.endPoint.y, line.x2, line.y2], { - fontSize: polygon.fontSize, - stroke: 'black', - strokeWidth: 3, - }) - delIndexs.push(polygonLines.indexOf(line)) - canvas.remove(polygonLines[polygonLines.indexOf(line)]) - if (newLine1.length / 10 > 10) { - newLines.push(newLine1) - } - if (newLine2.length / 10 > 10) { - newLines.push(newLine2) - } - } - }) - }) - polygonLines = polygonLines.filter((line) => !delIndexs.includes(line.tempIndex)) - polygonLines = [...polygonLines, ...newLines] - - const allLines = [...polygonLines, ...innerLines] - - /** - * 왼쪽 상단을 startPoint로 전부 변경 - */ - allLines.forEach((line) => { - let startPoint // 시작점 - let endPoint // 끝점 - if (line.x1 < line.x2) { - startPoint = { x: line.x1, y: line.y1 } - endPoint = { x: line.x2, y: line.y2 } - } else if (line.x1 > line.x2) { - startPoint = { x: line.x2, y: line.y2 } - endPoint = { x: line.x1, y: line.y1 } - } else { - if (line.y1 < line.y2) { - startPoint = { x: line.x1, y: line.y1 } - endPoint = { x: line.x2, y: line.y2 } - } else { - startPoint = { x: line.x2, y: line.y2 } - endPoint = { x: line.x1, y: line.y1 } - } - } - - line.startPoint = startPoint - line.endPoint = endPoint - }) - - polygonLines.forEach((line) => { - const startPoint = line.startPoint // 시작점 - let arrivalPoint = line.endPoint // 도착점 - - let currentPoint = startPoint - const roofPoints = [startPoint] - - const startLine = line - const visitPoints = [startPoint] - const visitLines = [startLine] - let cnt = 0 - - while (!isSamePoint(currentPoint, arrivalPoint)) { - line.set({ stroke: 'red' }) - canvas.renderAll() - let nextLines = allLines.filter( - (line2) => - (isSamePoint(line2.startPoint, currentPoint) || isSamePoint(line2.endPoint, currentPoint)) && - line !== line2 && - innerLines.includes(line2) && - !visitLines.includes(line2), - ) - - if (nextLines.length === 0) { - nextLines = allLines.filter( - (line2) => - (isSamePoint(line2.startPoint, currentPoint) || isSamePoint(line2.endPoint, currentPoint)) && - line !== line2 && - !visitLines.includes(line2), - ) - } - - if (!nextLines) { - break - } - - let comparisonPoints = [] - - nextLines.forEach((nextLine) => { - if (isSamePoint(nextLine.startPoint, currentPoint)) { - comparisonPoints.push(nextLine.endPoint) - } else { - comparisonPoints.push(nextLine.startPoint) - } - }) - - comparisonPoints = comparisonPoints.filter((point) => !visitPoints.some((visitPoint) => isSamePoint(visitPoint, point))) - comparisonPoints = comparisonPoints.filter((point) => !isSamePoint(point, currentPoint)) - - const minDistancePoint = comparisonPoints.reduce((prev, current) => { - const prevDistance = Math.sqrt(Math.pow(prev.x - arrivalPoint.x, 2) + Math.pow(prev.y - arrivalPoint.y, 2)) - const currentDistance = Math.sqrt(Math.pow(current.x - arrivalPoint.x, 2) + Math.pow(current.y - arrivalPoint.y, 2)) - - return prevDistance < currentDistance ? prev : current - }, comparisonPoints[0]) - - nextLines.forEach((nextLine) => { - if (isSamePoint(nextLine.startPoint, minDistancePoint) || isSamePoint(nextLine.endPoint, minDistancePoint)) { - visitLines.push(nextLine) - } - }) - - currentPoint = { ...minDistancePoint } - roofPoints.push(currentPoint) - cnt++ - if (cnt > 100) { - throw new Error('무한루프') - } - } - roofs.push(roofPoints) - }) - - const newRoofs = removeDuplicatePolygons(roofs) - - newRoofs.forEach((roofPoint, index) => { - let defense, pitch - const polygonLines = [...polygon.lines] - - let representLines = [] - let representLine - - // 지붕을 그리면서 기존 polygon의 line중 연결된 line을 찾는다. - polygonLines.forEach((line) => { - let startFlag = false - let endFlag = false - const startPoint = line.startPoint - const endPoint = line.endPoint - roofPoint.forEach((point, index) => { - if (isSamePoint(point, startPoint)) { - startFlag = true - } - if (isSamePoint(point, endPoint)) { - endFlag = true - } - }) - - if (startFlag && endFlag) { - representLines.push(line) - } - }) - - // representLines중 가장 긴 line을 찾는다. - representLines.forEach((line) => { - if (!representLine) { - representLine = line - } else { - if (representLine.length < line.length) { - representLine = line - } - } - }) - - const direction = newRoofs.length === 1 ? polygon.direction : representLine.direction - const polygonDirection = polygon.direction - - switch (direction) { - case 'top': - defense = 'east' - break - case 'right': - defense = 'south' - break - case 'bottom': - defense = 'west' - break - case 'left': - defense = 'north' - break - } - pitch = polygon.lines[index].attributes?.pitch ?? 0 - - const roof = new QPolygon(roofPoint, { - fontSize: polygon.fontSize, - stroke: 'black', - fill: 'transparent', - strokeWidth: 3, - name: POLYGON_TYPE.ROOF, - originX: 'center', - originY: 'center', - selectable: true, - defense: defense, - direction: newRoofs.length === 1 ? polygonDirection : defense, - pitch: pitch, - }) - - polygon.canvas.add(roof) - canvas.remove(polygon) - polygon.canvas.renderAll() - }) -} function normalizePoint(point) { return { @@ -1434,7 +1194,7 @@ function arePolygonsEqual(polygon1, polygon2) { return normalizedPolygon1.every((point, index) => arePointsEqual(point, normalizedPolygon2[index])) } -function removeDuplicatePolygons(polygons) { +export function removeDuplicatePolygons(polygons) { const uniquePolygons = [] polygons.forEach((polygon) => { From c0396c9d6f3d9ec657c3998ec8b363521fb4c099 Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Thu, 7 Nov 2024 17:05:29 +0900 Subject: [PATCH 25/51] =?UTF-8?q?=EB=B3=B4=EC=A1=B0=EC=84=A0=20actualSize?= =?UTF-8?q?=200=EC=9C=BC=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/fabric/QPolygon.js | 3 ++- src/hooks/roofcover/useAuxiliaryDrawing.js | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/components/fabric/QPolygon.js b/src/components/fabric/QPolygon.js index 339c9203..3db4f743 100644 --- a/src/components/fabric/QPolygon.js +++ b/src/components/fabric/QPolygon.js @@ -138,7 +138,8 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { }) this.on('removed', () => { - const children = getAllRelatedObjects(this.id, this.canvas) + // const children = getAllRelatedObjects(this.id, this.canvas) + const children = this.canvas.getObjects().filter((obj) => obj.parentId === this.id && obj.name === 'lengthText') children.forEach((child) => { this.canvas.remove(child) }) diff --git a/src/hooks/roofcover/useAuxiliaryDrawing.js b/src/hooks/roofcover/useAuxiliaryDrawing.js index e9aa7d93..6e95e79c 100644 --- a/src/hooks/roofcover/useAuxiliaryDrawing.js +++ b/src/hooks/roofcover/useAuxiliaryDrawing.js @@ -815,7 +815,7 @@ export function useAuxiliaryDrawing(id) { roofBase.lines.some((line) => isPointOnLine(line, { x: line.x2, y: line.y2 })) if (inPolygon1 && inPolygon2) { - line.attributes = { ...line.attributes, roofId: roofBase.id } + line.attributes = { ...line.attributes, roofId: roofBase.id, actualSize: 0, planeSize: line.getLength() } return true } }) From 72c7fc263a6726bcbbf9b88985fb25e68288ed9e Mon Sep 17 00:00:00 2001 From: Jaeyoung Lee Date: Thu, 7 Nov 2024 17:07:11 +0900 Subject: [PATCH 26/51] =?UTF-8?q?=EB=A7=88=EB=A3=A8=20=EA=B3=84=EC=82=B0?= =?UTF-8?q?=20=EC=88=98=EC=8B=9D=20=EC=A1=B0=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/fabric/QPolygon.js | 1 - src/hooks/useMode.js | 2 +- src/util/qpolygon-utils.js | 32 +++++++++++++++---------------- 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/components/fabric/QPolygon.js b/src/components/fabric/QPolygon.js index 339c9203..873d2c6a 100644 --- a/src/components/fabric/QPolygon.js +++ b/src/components/fabric/QPolygon.js @@ -231,7 +231,6 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { if (eaves.length > 0) { const gables = this.lines.filter((line) => sheds.includes(line) === false && eaves.includes(line) === false) const isGable = gables.every((line) => gableType.includes(line.attributes.type)) - console.log('isGable : ', isGable) if (isGable) { drawShedRoof(this.id, this.canvas) } else { diff --git a/src/hooks/useMode.js b/src/hooks/useMode.js index 703b622d..84c4fac6 100644 --- a/src/hooks/useMode.js +++ b/src/hooks/useMode.js @@ -36,7 +36,7 @@ import { QPolygon } from '@/components/fabric/QPolygon' import offsetPolygon from '@/util/qpolygon-utils' import { isObjectNotEmpty } from '@/util/common-utils' import * as turf from '@turf/turf' -import { INPUT_TYPE, Mode, POLYGON_TYPE } from '@/common/common' +import { INPUT_TYPE, LINE_TYPE, Mode, POLYGON_TYPE } from '@/common/common' export function useMode() { const [mode, setMode] = useRecoilState(modeState) diff --git a/src/util/qpolygon-utils.js b/src/util/qpolygon-utils.js index 16a73098..d3f02ef8 100644 --- a/src/util/qpolygon-utils.js +++ b/src/util/qpolygon-utils.js @@ -1807,8 +1807,8 @@ const drawRidge = (roof, canvas) => { attributes: { roofId: roof.id }, }, ) - ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 - ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 + ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) + ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) canvas.add(ridge) roof.ridges.push(ridge) @@ -1850,8 +1850,8 @@ const drawRidge = (roof, canvas) => { roof.ridges = roof.ridges.filter((r) => !(ridge2.x1 === r.x1 && ridge2.y1 === r.y1 && ridge2.x2 === r.x2 && ridge2.y2 === r.y2)) roof.innerLines = roof.innerLines.filter((r) => !(ridge.x1 === r.x1 && ridge.y1 === r.y1 && ridge.x2 === r.x2 && ridge.y2 === r.y2)) roof.innerLines = roof.innerLines.filter((r) => !(ridge2.x1 === r.x1 && ridge2.y1 === r.y1 && ridge2.x2 === r.x2 && ridge2.y2 === r.y2)) - newRidge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 - newRidge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 + newRidge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) + newRidge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) canvas.add(newRidge) roof.ridges.push(newRidge) roof.innerLines.push(newRidge) @@ -2221,8 +2221,8 @@ const connectLinePoint = (polygon) => { stroke: 'purple', strokeWidth: 1, }) - line.attributes.planeSize = Math.round(Math.sqrt(Math.pow(line.x1 - line.x2, 2) + Math.pow(line.y1 - line.y2, 2)) * 10) / 10 - line.attributes.actualSize = Math.round(Math.sqrt(Math.pow(line.x1 - line.x2, 2) + Math.pow(line.y1 - line.y2, 2)) * 10) / 10 + line.attributes.planeSize = Math.round(Math.sqrt(Math.pow(line.x1 - line.x2, 2) + Math.pow(line.y1 - line.y2, 2)) * 10) + line.attributes.actualSize = Math.round(Math.sqrt(Math.pow(line.x1 - line.x2, 2) + Math.pow(line.y1 - line.y2, 2)) * 10) polygon.canvas.add(line) polygon.innerLines.push(line) }) @@ -2527,8 +2527,8 @@ const changeEavesRoof = (currentRoof, canvas) => { hipX2 = midX - addHipX2 hipY2 = midY - addHipY2 } - ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 - ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 + ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) + ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) } hipLines.forEach((hip) => { @@ -2706,8 +2706,8 @@ const changeGableRoof = (currentRoof, canvas) => { }) currentRoof.attributes.ridgeCoordinate = { x1: ridge.x2, y1: ridge.y2 } } - ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 - ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 + ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) + ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) let hip1 = new QLine([currentRoof.x1, currentRoof.y1, midX, midY], { fontSize: roof.fontSize, @@ -2890,8 +2890,8 @@ const changeHipAndGableRoof = (currentRoof, canvas) => { }) currentRoof.attributes.ridgeCoordinate = { x1: ridge.x2, y1: ridge.y2 } } - ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 - ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 + ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) + ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) } const hip1 = new QLine([currentRoof.x1, currentRoof.y1, midX + hipX2, midY + hipY2], { @@ -3128,8 +3128,8 @@ const changeJerkInHeadRoof = (currentRoof, canvas) => { hipX2 = midX - xWidth hipY2 = midY - yWidth } - ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 - ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 + ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) + ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) } let hipX1 = (Math.sign(currentRoof.x1 - midX) * currentRoof.attributes.width) / 2 @@ -3427,8 +3427,8 @@ const changeWallRoof = (currentRoof, canvas) => { y2: ridge.y2 - diffY, }) } - ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 - ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) / 10 + ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) + ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) let hip1 = new QLine([currentRoof.x1, currentRoof.y1, wallMidX, wallMidY], { fontSize: roof.fontSize, From 8c1ded1126a462f4f27d0025c1a30ca764c3fb5b Mon Sep 17 00:00:00 2001 From: yjnoh Date: Thu, 7 Nov 2024 17:09:53 +0900 Subject: [PATCH 27/51] =?UTF-8?q?=EB=A9=B4=ED=98=95=EC=83=81=20=ED=81=AC?= =?UTF-8?q?=EA=B8=B0=20=EC=A1=B0=EC=A0=88,=20=EC=98=A4=EB=B8=8C=EC=A0=9D?= =?UTF-8?q?=ED=8A=B8=20=ED=81=AC=EA=B8=B0=EC=A1=B0=EC=A0=88=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/fabric/QPolygon.js | 34 +++++- .../floor-plan/modal/object/SizeSetting.jsx | 7 +- src/hooks/common/useCanvasConfigInitialize.js | 3 + src/hooks/object/useObjectBatch.js | 22 ++-- src/hooks/surface/useSurfaceShapeBatch.js | 113 ++++++++++-------- 5 files changed, 118 insertions(+), 61 deletions(-) diff --git a/src/components/fabric/QPolygon.js b/src/components/fabric/QPolygon.js index 44cbfb37..7df9d495 100644 --- a/src/components/fabric/QPolygon.js +++ b/src/components/fabric/QPolygon.js @@ -137,6 +137,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { }) }) + //QPolygon 좌표 이동시 좌표 재계산 this.on('polygonMoved', () => { //폴리곤일때만 사용 let matrix = this.calcTransformMatrix() @@ -148,8 +149,9 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { .map((p) => { return fabric.util.transformPoint(p, matrix) }) - this.set('points', transformedPoints) - this.set('pathOffset', { x: this.left, y: this.top }) + this.points = transformedPoints + const { left, top } = this.calcOriginCoords() + this.set('pathOffset', { x: left, y: top }) this.setCoords() }) @@ -773,4 +775,32 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { divideLine() { // splitPolygonWithLines(this) }, + calcOriginCoords() { + const points = this.points + const minX = Math.min(...points.map((p) => p.x)) + const maxX = Math.max(...points.map((p) => p.x)) + const minY = Math.min(...points.map((p) => p.y)) + const maxY = Math.max(...points.map((p) => p.y)) + + let left = 0 + let top = 0 + + if (this.originX === 'center') { + left = (minX + maxX) / 2 + } else if (this.originX === 'left') { + left = minX + } else if (this.originX === 'right') { + left = maxX + } + + if (this.originY === 'center') { + top = (minY + maxY) / 2 + } else if (this.originY === 'top') { + top = minY + } else if (this.originY === 'bottom') { + top = maxY + } + + return { left, top } + }, }) diff --git a/src/components/floor-plan/modal/object/SizeSetting.jsx b/src/components/floor-plan/modal/object/SizeSetting.jsx index 333150ea..cadfd461 100644 --- a/src/components/floor-plan/modal/object/SizeSetting.jsx +++ b/src/components/floor-plan/modal/object/SizeSetting.jsx @@ -18,7 +18,7 @@ export default function SizeSetting(props) { const { getMessage } = useMessage() const { closePopup } = usePopup() const { resizeObjectBatch } = useObjectBatch({}) - const { reSizePolygon } = useSurfaceShapeBatch() + const { resizeSurfaceShapeBatch } = useSurfaceShapeBatch() const widthRef = useRef(null) const heightRef = useRef(null) @@ -36,10 +36,11 @@ export default function SizeSetting(props) { target.name === BATCH_TYPE.OPENING || target.name === BATCH_TYPE.SHADOW || target.name === BATCH_TYPE.TRIANGLE_DORMER || - target.name === BATCH_TYPE.PENTAGON_DORMER || - target.name === POLYGON_TYPE.ROOF + target.name === BATCH_TYPE.PENTAGON_DORMER ) { resizeObjectBatch(settingTarget, target, width, height) + } else if (target.name === POLYGON_TYPE.ROOF) { + resizeSurfaceShapeBatch(settingTarget, target, width, height) } } diff --git a/src/hooks/common/useCanvasConfigInitialize.js b/src/hooks/common/useCanvasConfigInitialize.js index c4f137b0..a07d4a00 100644 --- a/src/hooks/common/useCanvasConfigInitialize.js +++ b/src/hooks/common/useCanvasConfigInitialize.js @@ -7,6 +7,7 @@ import { useFont } from '@/hooks/common/useFont' import { useGrid } from '@/hooks/common/useGrid' import { globalFontAtom } from '@/store/fontAtom' import { useRoof } from '@/hooks/common/useRoof' +import { usePolygon } from '@/hooks/usePolygon' export function useCanvasConfigInitialize() { const canvas = useRecoilValue(canvasState) @@ -20,6 +21,7 @@ export function useCanvasConfigInitialize() { const {} = useFont() const {} = useGrid() const {} = useRoof() + const { drawDirectionArrow } = usePolygon() useEffect(() => { if (!canvas) return @@ -173,6 +175,7 @@ export function useCanvasConfigInitialize() { //그룹 객체로 다시 만든다 (좌표때문에) const group = new fabric.Group(objectArray, { + ...objectArray, groupId: id, name: objectsName, selectable: true, diff --git a/src/hooks/object/useObjectBatch.js b/src/hooks/object/useObjectBatch.js index a16ce0f9..1820599b 100644 --- a/src/hooks/object/useObjectBatch.js +++ b/src/hooks/object/useObjectBatch.js @@ -374,6 +374,9 @@ export function useObjectBatch({ isHidden, setIsHidden }) { const trianglePolygon = pointsToTurfPolygon(triangleToPolygon(dormer)) const selectedSurfacePolygon = polygonToTurfPolygon(selectedSurface) + console.log('trianglePolygon', trianglePolygon) + console.log('selectedSurfacePolygon', selectedSurfacePolygon) + //지붕 밖으로 그렸을때 if (!turf.booleanWithin(trianglePolygon, selectedSurfacePolygon)) { swalFire({ text: '도머를 배치할 수 없습니다.', icon: 'error' }) @@ -496,6 +499,10 @@ export function useObjectBatch({ isHidden, setIsHidden }) { }) canvas?.add(objectGroup) + objectGroup.getObjects().forEach((obj, index) => { + console.log(`최초 pathOffset ${index}`, obj.get('pathOffset')) + }) + isDown = false initEvent() dbClickEvent() @@ -917,20 +924,17 @@ export function useObjectBatch({ isHidden, setIsHidden }) { originY: 'center', left: changedCoords.x, top: changedCoords.y, + width: width / 10, + height: height / 10, }) - if (target.name === 'roof') { - //얘는 일단 도머에 적용함 - if (target.type === 'group') { - target._objects.forEach((obj) => setSurfaceShapePattern(obj)) - } else { - setSurfaceShapePattern(target) - target.fire('modified') - } + //얘는 일단 도머에 적용함 + if (target.type === 'group') { + target._objects.forEach((obj) => setSurfaceShapePattern(obj)) } + // target.setCoords() canvas.renderAll() - if (target.type === 'group') reGroupObject(target) } diff --git a/src/hooks/surface/useSurfaceShapeBatch.js b/src/hooks/surface/useSurfaceShapeBatch.js index 9457169c..d2c6aee7 100644 --- a/src/hooks/surface/useSurfaceShapeBatch.js +++ b/src/hooks/surface/useSurfaceShapeBatch.js @@ -657,7 +657,7 @@ export function useSurfaceShapeBatch() { } function getAllRelatedObjects(id) { - const result = [] + const ult = [] const map = new Map() // Create a map of objects by their id @@ -688,52 +688,8 @@ export function useSurfaceShapeBatch() { const roof = canvas.getActiveObject() if (roof) { - let isDragging = false - const childrenObjects = canvas.getObjects().filter((obj) => obj.parentId === roof.id) - console.log('childrenObjects', childrenObjects) - - // const groupObjects = canvas.getObjects().filter((obj) => obj.parentId === roof.id && obj.type === 'group') - - // const ungroupObjects = [] // 그룹 해제된 객체들 - // const groupChildObjects = [] - - // groupObjects.forEach((obj) => { - // obj._restoreObjectsState() - // obj.getObjects().forEach((o) => { - // o.set({ - // ungroupYn: true, - // }) - // canvas.add(o) - // ungroupObjects.push(o) - // }) - // canvas.remove(obj) - // }) - - // const childObjects = findAllChildren(roof.id) - // groupObjects.forEach((obj) => { - // groupChildObjects.push(...obj.getObjects()) - // }) - - // console.log('ungroupObjects', ungroupObjects) - // console.log('childObjects', childObjects) - // console.log('groupChildObjects', groupChildObjects) - - // const children = canvas.getObjects().filter((obj) => obj.parentId === roof.id) - // let grandChildren = [] - - // children.forEach((child) => { - // if (child.type === 'group') { - // child.getObjects().forEach((grandChild) => { - // const groupObjects = canvas.getObjects().filter((obj) => obj.parentId === grandChild.id) - // grandChildren.push(...groupObjects) - // }) - // } else { - // grandChildren.push(...canvas.getObjects().filter((obj) => obj.parentId === child.id)) - // } - // }) - const selectionArray = [roof, ...childrenObjects] const selection = new fabric.ActiveSelection(selectionArray, { @@ -748,7 +704,6 @@ export function useSurfaceShapeBatch() { canvas.setActiveObject(selection) addCanvasMouseEventListener('mouse:up', (e) => { - isDragging = false canvas.selection = true canvas.discardActiveObject() // 모든 선택 해제 @@ -768,7 +723,6 @@ export function useSurfaceShapeBatch() { canvas.renderAll() roof.fire('polygonMoved') - if (roof.type === 'group') reGroupObject(obj) drawDirectionArrow(roof) initEvent() }) @@ -805,9 +759,74 @@ export function useSurfaceShapeBatch() { canvas?.remove(groupObj) } + const resizeSurfaceShapeBatch = (side, target, width, height) => { + const objectWidth = target.width + const objectHeight = target.height + const changeWidth = width / 10 / objectWidth + const changeHeight = height / 10 / objectHeight + let sideX = 'left' + let sideY = 'top' + + //그룹 중심점 변경 + if (side === 2) { + sideX = 'right' + sideY = 'top' + } else if (side === 3) { + sideX = 'left' + sideY = 'bottom' + } else if (side === 4) { + sideX = 'right' + sideY = 'bottom' + } + + //변경 전 좌표 + const newCoords = target.getPointByOrigin(sideX, sideY) + + target.set({ + originX: sideX, + originY: sideY, + left: newCoords.x, + top: newCoords.y, + }) + + target.scaleX = changeWidth + target.scaleY = changeHeight + + const currentPoints = target.getCurrentPoints() + + target.set({ + scaleX: 1, + scaleY: 1, + width: parseInt((width / 10).toFixed(0)), + height: parseInt((height / 10).toFixed(0)), + }) + //크기 변경후 좌표를 재 적용 + const changedCoords = target.getPointByOrigin('center', 'center') + + target.set({ + originX: 'center', + originY: 'center', + left: changedCoords.x, + top: changedCoords.y, + }) + + //면형상 리사이즈시에만 + target.fire('polygonMoved') + target.points = currentPoints + target.fire('modified') + + setSurfaceShapePattern(target, roofDisplay.column) + if (target.direction) { + drawDirectionArrow(target) + } + target.setCoords() + canvas.renderAll() + } + return { applySurfaceShape, deleteAllSurfacesAndObjects, moveSurfaceShapeBatch, + resizeSurfaceShapeBatch, } } From ed8a9816313c8441e9cc43db319a56011922b06f Mon Sep 17 00:00:00 2001 From: leeyongjae Date: Thu, 7 Nov 2024 17:40:57 +0900 Subject: [PATCH 28/51] =?UTF-8?q?=EB=B0=9C=EC=A0=84=EC=8B=9C=EB=AE=AC?= =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=85=98=20=EC=9E=84=EC=8B=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 + src/app/floor-plan/simulator/[mid]/page.jsx | 9 + src/components/floor-plan/CanvasMenu.jsx | 3 + src/components/simulator/Simulator.jsx | 398 ++++++++++++++++++++ yarn.lock | 17 + 5 files changed, 429 insertions(+) create mode 100644 src/app/floor-plan/simulator/[mid]/page.jsx create mode 100644 src/components/simulator/Simulator.jsx diff --git a/package.json b/package.json index 6c94a282..f338fbe4 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "@nextui-org/react": "^2.4.2", "ag-grid-react": "^32.0.2", "axios": "^1.7.3", + "chart.js": "^4.4.6", "fabric": "^5.3.0", "framer-motion": "^11.2.13", "fs": "^0.0.1-security", @@ -22,6 +23,7 @@ "next": "14.2.3", "next-international": "^1.2.4", "react": "^18", + "react-chartjs-2": "^5.2.0", "react-colorful": "^5.6.1", "react-datepicker": "^7.3.0", "react-dom": "^18", diff --git a/src/app/floor-plan/simulator/[mid]/page.jsx b/src/app/floor-plan/simulator/[mid]/page.jsx new file mode 100644 index 00000000..939e1cc4 --- /dev/null +++ b/src/app/floor-plan/simulator/[mid]/page.jsx @@ -0,0 +1,9 @@ +import Simulator from '@/components/simulator/Simulator' + +export default function SimulatorPage() { + return ( + <> + + + ) +} diff --git a/src/components/floor-plan/CanvasMenu.jsx b/src/components/floor-plan/CanvasMenu.jsx index 326bc4f4..613db2bd 100644 --- a/src/components/floor-plan/CanvasMenu.jsx +++ b/src/components/floor-plan/CanvasMenu.jsx @@ -81,6 +81,9 @@ export default function CanvasMenu(props) { case 4: setType('module') break + case 6: + router.push(`/floor-plan/simulator/${menu.index}`) + break } if (pathname !== '/floor-plan') router.push('/floor-plan') diff --git a/src/components/simulator/Simulator.jsx b/src/components/simulator/Simulator.jsx new file mode 100644 index 00000000..9e7768a1 --- /dev/null +++ b/src/components/simulator/Simulator.jsx @@ -0,0 +1,398 @@ +'use client' + +import 'chart.js/auto' +import { Bar } from 'react-chartjs-2' +import dayjs from 'dayjs' + +import { useEffect, useState } from 'react' +import { useRecoilState, useRecoilValue } from 'recoil' +import { floorPlanObjectState } from '@/store/floorPlanObjectAtom' + +import { useAxios } from '@/hooks/useAxios' +import { useMessage } from '@/hooks/useMessage' +import { usePlan } from '@/hooks/usePlan' +import { useCommonCode } from '@/hooks/common/useCommonCode' +import { useCanvasMenu } from '@/hooks/common/useCanvasMenu' + +import { convertNumberToPriceDecimal, isEmptyArray } from '@/util/common-utils' + +export default function Simulator() { + const { plans } = usePlan() + const plan = plans.find((plan) => plan.isCurrent === true) + + // recoil 물건번호 + const objectRecoil = useRecoilValue(floorPlanObjectState) + const [objectNo, setObjectNo] = useState('') + + useEffect(() => { + setObjectNo(objectRecoil.floorPlanObjectNo) + }, [objectRecoil]) + + // 캔버스 메뉴 넘버 셋팅 + const { setMenuNumber } = useCanvasMenu() + + useEffect(() => { + setMenuNumber(6) + }, []) + + const { get } = useAxios() + const { getMessage } = useMessage() + + // 공통코드 조회 + const { commonCode, findCommonCode } = useCommonCode() + const [prefCodeList, setPrefCodeList] = useState([]) // 도도부현 코드 + const [areaIdList, setAreaIdList] = useState([]) // 시뮬레이션 코드 + const [windSpeedList, setWindSpeedList] = useState([]) // 기준 풍속 공통코드 + + useEffect(() => { + const code1 = findCommonCode(202000) // 기준풍속 + if (code1 != null) { + setWindSpeedList(code1) + } + }, [commonCode]) + + const chartData = [ + Math.floor(Math.random() * 1000), + Math.floor(Math.random() * 2000), + Math.floor(Math.random() * 3000), + Math.floor(Math.random() * 4000), + Math.floor(Math.random() * 5000), + Math.floor(Math.random() * 6000), + Math.floor(Math.random() * 6000), + Math.floor(Math.random() * 5000), + Math.floor(Math.random() * 4000), + Math.floor(Math.random() * 3000), + Math.floor(Math.random() * 2000), + Math.floor(Math.random() * 1000), + ] + + // 차트 관련 + const data = { + labels: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'], + datasets: [ + { + label: 'kWh', + data: chartData, + + backgroundColor: [ + 'rgba(255, 99, 132, 0.2)', + 'rgba(54, 162, 235, 0.2)', + 'rgba(255, 206, 86, 0.2)', + 'rgba(75, 192, 192, 0.2)', + 'rgba(153, 102, 255, 0.2)', + 'rgba(255, 159, 64, 0.2)', + 'rgba(0, 99, 132, 0.2)', + 'rgba(0, 162, 235, 0.2)', + 'rgba(0, 206, 86, 0.2)', + 'rgba(0, 192, 192, 0.2)', + 'rgba(0, 102, 255, 0.2)', + 'rgba(0, 159, 64, 0.2)', + ], + borderColor: [ + 'rgba(255, 99, 132, 0.2)', + 'rgba(54, 162, 235, 0.2)', + 'rgba(255, 206, 86, 0.2)', + 'rgba(75, 192, 192, 0.2)', + 'rgba(153, 102, 255, 0.2)', + 'rgba(255, 159, 64, 0.2)', + 'rgba(0, 99, 132, 0.2)', + 'rgba(0, 162, 235, 0.2)', + 'rgba(0, 206, 86, 0.2)', + 'rgba(0, 192, 192, 0.2)', + 'rgba(0, 102, 255, 0.2)', + 'rgba(0, 159, 64, 0.2)', + ], + borderWidth: 1, + }, + ], + } + + const options = { + plugins: { + legend: { + position: 'top', + }, + }, + scales: { + x: { + grid: { + display: false, + }, + }, + y: { + beginAtZero: true, + grid: { + display: true, + }, + }, + }, + } + + useEffect(() => { + if (objectNo) { + fetchObjectDetail(objectNo) + } + fetchSimulatorNotice() + }, [objectNo]) + + // 물건 상세 정보 조회 + const [objectDetail, setObjectDetail] = useState({}) + + const fetchObjectDetail = async (objectNo) => { + const apiUrl = `/api/object/${objectNo}/detail` + const resultData = await get({ url: apiUrl }) + + if (resultData) { + if (resultData.prefId) { + get({ url: '/api/object/prefecture/list' }).then((res) => { + if (!isEmptyArray(res)) { + setPrefCodeList(res) + } + }) + get({ url: `/api/object/prefecture/${resultData.prefId}/list` }).then((res) => { + if (!isEmptyArray(res)) { + setAreaIdList(res) + } + }) + } + setObjectDetail(resultData) + } + } + + // 모듈배치정보 조회 + const [moduleInfoList, setModuleInfoList] = useState([]) + + // 파워컨디셔너 조회 + const [pcsInfoList, setPcsInfoList] = useState([]) + + // 시뮬레이션 안내사항 조회 + const [content, setContent] = useState('') + + const fetchSimulatorNotice = async () => { + const resultData = '1234123\r\n12\r\n3\r\n123\r\n12\r\n312\r\n312\r\n3123123123123\r\n\r\nㅅㄷㄴㅅ\r\nㅁㅅㄷㄴㅁㅅㄴㅁㅅㄴㅅ' + if (resultData) { + setContent(resultData.replaceAll('\n', '
')) + } else { + setContent(getMessage('common.message.no.data')) + } + } + + return ( +
+
+
+
+
+ {/* 물건번호 */} +
+
{getMessage('simulator.title.sub1')}
+
+ {objectNo} (Plan No: {plan?.id}) +
+
+ {/* 작성일 */} +
+
{getMessage('simulator.title.sub2')}
+
{`${dayjs(objectDetail.lastEditDatetime).format('YYYY.MM.DD')}`}
+
+ {/* 시스템용량 */} +
+
{getMessage('simulator.title.sub3')}
+
??? kW
+
+ {/* 연간예측발전량 */} +
+
{getMessage('simulator.title.sub4')}
+
???
+
+
+
+ {/* 도도부현 */} +
+
{getMessage('simulator.title.sub5')}
+
+ {prefCodeList.map((prefCode) => (prefCode.prefId === objectDetail.prefId ? prefCode.prefName : ''))} + {` `} + {objectDetail.address} +
+
+ {/* 일사량 관측지점 */} +
+
{getMessage('simulator.title.sub6')}
+
+ {areaIdList.map((areaCode) => (areaCode.areaId === objectDetail.areaId ? areaCode.prefName : ''))} +
+
+ {/* 적설조건 */} +
+
{getMessage('simulator.title.sub7')}
+
+ {objectDetail.verticalSnowCover} + {objectDetail.verticalSnowCover && 'cm'} +
+
+ {/* 풍속조건 */} +
+
{getMessage('simulator.title.sub8')}
+
+ {windSpeedList.map((windSpeed) => (windSpeed.clCode === objectDetail.standardWindSpeedId ? windSpeed.clCodeNm : ''))} +
+
+
+
+
+
+
+
+
+
+ +
+
+
+

{getMessage('simulator.table.sub9')}

+
+
+ {/* 예측발전량 */} +
+ + + + + + + + + + + + + + + + + + + + + {chartData.map((data) => ( + + ))} + + + +
1月2月3月4月5月6月7月8月9月10月11月12月{getMessage('simulator.table.sub6')}
{convertNumberToPriceDecimal(data)}{convertNumberToPriceDecimal(chartData.reduce((a, b) => a + b))}
+
+
+
+
+
+
+ + + + + + + + + + + + {moduleInfoList.length > 0 ? ( + moduleInfoList.map((moduleInfo) => { + return ( + <> + + {/* 지붕면 */} + + {/* 경사각 */} + + {/* 방위각(도) */} + + {/* 태양전지모듈 */} + + {/* 매수 */} + + + + ) + }) + ) : ( + + + + )} + +
{getMessage('simulator.table.sub1')}{getMessage('simulator.table.sub2')}{getMessage('simulator.table.sub3')}{getMessage('simulator.table.sub4')}{getMessage('simulator.table.sub5')}
西南西10.3寸81 +
Re.RISE-G2 415
+
20
{getMessage('common.message.no.data')}
+ {moduleInfoList.length > 0 && ( +
+
{getMessage('simulator.table.sub6')}
+
0
+
+ )} +
+
+
+
+ + + + + + + + + {pcsInfoList.length > 0 ? ( + pcsInfoList.map((pcsInfo) => { + return ( + <> + + {/* 파워컨디셔너 */} + + {/* 대 */} + + + + ) + }) + ) : ( + + + + )} + +
{getMessage('simulator.table.sub7')}{getMessage('simulator.table.sub8')}
+
HQJP-MA55-3
+
2
{getMessage('common.message.no.data')}
+
+
+
+
+
+
+
+
+
+ + {getMessage('simulator.notice.sub1')} +
+ {getMessage('simulator.notice.sub2')} +
+
+ {/* 시뮬레이션 안내사항 */} +
+
+
+
+
+
+ ) +} diff --git a/yarn.lock b/yarn.lock index a167fa9d..ed2cceda 100644 --- a/yarn.lock +++ b/yarn.lock @@ -527,6 +527,11 @@ resolved "https://registry.npmjs.org/@js-joda/core/-/core-5.6.3.tgz" integrity sha512-T1rRxzdqkEXcou0ZprN1q9yDRlvzCPLqmlNt5IIsGBzoEVgLCCYrKEwc84+TvsXuAc95VAZwtWD2zVsKPY4bcA== +"@kurkle/color@^0.3.0": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@kurkle/color/-/color-0.3.2.tgz#5acd38242e8bde4f9986e7913c8fdf49d3aa199f" + integrity sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw== + "@mapbox/node-pre-gyp@^1.0.0": version "1.0.11" resolved "https://registry.yarnpkg.com/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz#417db42b7f5323d79e93b34a6d7a2a12c0df43fa" @@ -4337,6 +4342,13 @@ chalk@^2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" +chart.js@^4.4.6: + version "4.4.6" + resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-4.4.6.tgz#da39b84ca752298270d4c0519675c7659936abec" + integrity sha512-8Y406zevUPbbIBA/HRk33khEmQPk5+cxeflWE/2rx1NJsjVWMPw/9mSP9rxHP5eqi6LNoPBVMfZHxbwLSgldYA== + dependencies: + "@kurkle/color" "^0.3.0" + "chokidar@>=3.0.0 <4.0.0", chokidar@^3.5.3: version "3.6.0" resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz" @@ -5832,6 +5844,11 @@ rbush@^3.0.1: dependencies: quickselect "^2.0.0" +react-chartjs-2@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/react-chartjs-2/-/react-chartjs-2-5.2.0.tgz#43c1e3549071c00a1a083ecbd26c1ad34d385f5d" + integrity sha512-98iN5aguJyVSxp5U3CblRLH67J8gkfyGNbiK3c+l1QI/G4irHMPQw44aEPmjVag+YKTyQ260NcF82GTQ3bdscA== + react-color-palette@^7.2.2: version "7.2.2" resolved "https://registry.npmjs.org/react-color-palette/-/react-color-palette-7.2.2.tgz" From 6f0f0883f8c14b78940b1a73d879d477ca1ba142 Mon Sep 17 00:00:00 2001 From: basssy Date: Thu, 7 Nov 2024 17:57:54 +0900 Subject: [PATCH 29/51] =?UTF-8?q?=EA=B2=AC=EC=A0=81=EC=84=9C=20=EC=83=81?= =?UTF-8?q?=EC=84=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/estimate/Estimate.jsx | 173 ++++++++++++++++-- .../estimate/useEstimateController.js | 121 ++++++------ src/locales/ja.json | 15 +- src/locales/ko.json | 15 +- 4 files changed, 249 insertions(+), 75 deletions(-) diff --git a/src/components/estimate/Estimate.jsx b/src/components/estimate/Estimate.jsx index f794cb50..87aa3397 100644 --- a/src/components/estimate/Estimate.jsx +++ b/src/components/estimate/Estimate.jsx @@ -9,12 +9,13 @@ import SingleDatePicker from '../common/datepicker/SingleDatePicker' import EstimateFileUploader from './EstimateFileUploader' import { useAxios } from '@/hooks/useAxios' import { globalLocaleStore } from '@/store/localeAtom' -import { isNotEmptyArray, isObjectNotEmpty } from '@/util/common-utils' +import { isNotEmptyArray, isObjectNotEmpty, queryStringFormatter } from '@/util/common-utils' import dayjs from 'dayjs' import { useCommonCode } from '@/hooks/common/useCommonCode' -import Select from 'react-select' import { useEstimateController } from '@/hooks/floorPlan/estimate/useEstimateController' import { SessionContext } from '@/app/SessionProvider' +import Select, { components } from 'react-select' +// import EstimateItemTable from './EstimateItemTable' export default function Estimate({ params }) { const { session } = useContext(SessionContext) @@ -33,6 +34,8 @@ export default function Estimate({ params }) { const { findCommonCode } = useCommonCode() const [honorificCodeList, setHonorificCodeList] = useState([]) //경칭 공통코드 + const [storePriceList, setStorePriceList] = useState([]) //가격표시 option + const [startDate, setStartDate] = useState(new Date()) const singleDatePickerProps = { startDate, @@ -44,7 +47,7 @@ export default function Estimate({ params }) { //견적서 상세데이터 const { state, setState } = useEstimateController(params.pid) - //견적특이사항 상세 데이터 LIST + const [itemList, setItemList] = useState([]) //견적특이사항 List const [specialNoteList, setSpecialNoteList] = useState([]) @@ -155,6 +158,46 @@ export default function Estimate({ params }) { }) } + //아이템 목록 + useEffect(() => { + if (isNotEmptyArray(state.itemList)) { + setItemList(state.itemList) + } + }, [state?.itemList]) + + //가격표시 option 세팅 + useEffect(() => { + const param = { + saleStoreId: session.storeId, + sapSalesStoreCd: session.custCd, + docTpCd: state?.estimateType, + } + const apiUrl = `/api/estimate/price/store-price-list?${queryStringFormatter(param)}` + get({ url: apiUrl }).then((res) => { + if (isNotEmptyArray(res?.data)) { + setStorePriceList(res.data) + } + }) + }, [state?.estimateType]) + + //Pricing 버튼 + const handlePricing = async (priceCd) => { + const param = { + saleStoreId: session.storeId, + sapSalesStoreCd: session.custCd, + docTpCd: state.estimateType, + priceCd: priceCd, + itemIdList: [], //아이템 + } + + console.log('param::', param) + return + await promisePost({ url: '/api/estimate/price/item-price-list', data: param }).then((res) => { + console.log('프라이싱결과::::::', res) + //아이템쪽 다 새로고침............SUCK!!! + }) + } + return (
@@ -304,6 +347,7 @@ export default function Estimate({ params }) { value={'YJSS'} checked={state?.estimateType === 'YJSS' ? true : false} onChange={(e) => { + //주문분류 setState({ estimateType: e.target.value }) }} /> @@ -380,9 +424,18 @@ export default function Estimate({ params }) {

{getMessage('estimate.detail.header.fileList1')}

- + { + setState({ + fileFlg: e.target.checked ? '1' : '0', + }) + }} + />
@@ -416,7 +469,7 @@ export default function Estimate({ params }) {
    - {isNotEmptyArray(originFiles) && + {originFiles.length > 0 && originFiles.map((originFile) => { return (
  • @@ -492,7 +545,7 @@ export default function Estimate({ params }) { } })}
- {/* 견적특이사항 선택한 내용?영역끝 */} + {/* 견적특이사항 선택한 내용 영역끝 */}
@@ -565,12 +618,30 @@ export default function Estimate({ params }) {
{getMessage('estimate.detail.header.showPrice')}
- + {session?.storeLvl === '1' ? ( + + ) : ( + + )}
- +
    @@ -605,7 +676,83 @@ export default function Estimate({ params }) {
{/* 가격표시영역끝 */} {/* html테이블시작 */} -
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+
{getMessage('estimate.detail.itemTableHeader.col1')}{getMessage('estimate.detail.itemTableHeader.col2')}{getMessage('estimate.detail.itemTableHeader.col3')}{getMessage('estimate.detail.itemTableHeader.col4')}{getMessage('estimate.detail.itemTableHeader.col5')}{getMessage('estimate.detail.itemTableHeader.col6')}{getMessage('estimate.detail.itemTableHeader.col7')}
+
+ + +
+
100 +
+
{/*
+
+
HNW-MC4-CHN30
+
+ + +
+
+
+
+ +
+
セット +
+
+ +
+
+ +
+
+
5,561,000
+
+ {/* html테이블끝 */}
diff --git a/src/hooks/floorPlan/estimate/useEstimateController.js b/src/hooks/floorPlan/estimate/useEstimateController.js index 2b92a14a..aeec4f1c 100644 --- a/src/hooks/floorPlan/estimate/useEstimateController.js +++ b/src/hooks/floorPlan/estimate/useEstimateController.js @@ -5,6 +5,7 @@ import { globalLocaleStore } from '@/store/localeAtom' import { estimateState, floorPlanObjectState } from '@/store/floorPlanObjectAtom' import { isObjectNotEmpty } from '@/util/common-utils' import { SessionContext } from '@/app/SessionProvider' +import { useMessage } from '@/hooks/useMessage' const reducer = (prevState, nextState) => { return { ...prevState, ...nextState } @@ -21,35 +22,33 @@ const defaultEstimateData = { estimateType: 'YJOD', //주문분류 remarks: '', //비고 estimateOption: '', //견적특이사항 - // itemList: [{ id: 1, name: '' }], //아이템에 필요없는거 빼기 itemList: [ - { - amount: '', - fileUploadFlg: '', - itemChangeFlg: '', - itemGroup: '', - itemId: '', //키값?? - itemName: '', - itemNo: '', - moduleFlg: '', - objectNo: '', - pkgMaterialFlg: '', - planNo: '', - pnowW: '', - salePrice: '', - saleTotPrice: '', - specification: '', - unit: '', - }, + // { + // amount: '', + // fileUploadFlg: '', + // itemChangeFlg: '', + // itemGroup: '', + // itemId: '', //키값?? + // itemName: '', + // itemNo: '', + // moduleFlg: '', + // objectNo: '', + // pkgMaterialFlg: '', + // planNo: '', + // pnowW: '', + // salePrice: '', + // saleTotPrice: '', + // specification: '', + // unit: '', + // }, ], fileList: [], + fileFlg: '0', //후일 자료 제출 (체크 1 노체크 0) } // Helper functions -// const updateItemInList = (itemList, id, updates) => { const updateItemInList = (itemList, itemId, updates) => { - // return itemList.map((item) => (item.id === id ? { ...item, ...updates } : item)) return itemList.map((item) => (item.itemId === itemId ? { ...item, ...updates } : item)) } @@ -59,6 +58,8 @@ export const useEstimateController = (planNo) => { const objectRecoil = useRecoilValue(floorPlanObjectState) const [estimateData, setEstimateData] = useRecoilState(estimateState) + const { getMessage } = useMessage() + const { get, post, promisePost } = useAxios(globalLocaleState) const [isLoading, setIsLoading] = useState(false) @@ -87,20 +88,15 @@ export const useEstimateController = (planNo) => { } } - // const updateItem = (id, updates) => { const updateItem = (itemId, updates) => { setState({ - // itemList: updateItemInList(state.itemList, id, updates), itemList: updateItemInList(state.itemList, itemId, updates), }) } const addItem = () => { - // const newId = Math.max(...state.itemList.map((item) => item.id)) + 1 const newItemId = Math.max(...state.itemList.map((item) => item.itemId)) + 1 setState({ - // itemList: [...state.itemList, { id: newId, name: '' }], - //셋팅할필요없는거 빼기 itemList: [ ...state.itemList, { @@ -126,42 +122,55 @@ export const useEstimateController = (planNo) => { } useEffect(() => { - setEstimateData({ ...state, userId: session.userId }) - //sapSalesStoreCd 추가예정 필수값 - // setEstimateData({ ...state, userId: session.userId, sapSalesStoreCd : session.sapSalesStoreCd }) + setEstimateData({ ...state, userId: session.userId, sapSalesStoreCd: session.custCd }) }, [state]) //견적서 저장 const handleEstimateSubmit = async () => { + //0. 필수체크 + let flag = true console.log('::담긴 estimateData:::', estimateData) - //1. 첨부파일 저장 - const formData = new FormData() - formData.append('file', estimateData.fileList) - formData.append('objectNo', estimateData.objectNo) - formData.append('planNo', estimateData.planNo) - formData.append('category', '10') - formData.append('userId', estimateData.userId) - for (const value of formData.values()) { - console.log('formData::', value) - } - - await promisePost({ url: '/api/file/fileUpload', data: formData }).then((res) => { - console.log('파일저장::::::::::', res) - }) - - //2. 상세데이터 저장 - - console.log('상세저장시작!!') - return - try { - const result = await promisePost({ - url: ESTIMATE_API_ENDPOINT, - data: estimateData, + //아이템 fileUploadFlg가1(첨부파일 필수)이 1개라도 있는데 후일 자료 제출(fileFlg) 체크안했으면(0) alert 저장안돼 + if (estimateData.itemList.length > 1) { + estimateData.itemList.map((row) => { + if (row.fileUploadFlg === '1') { + if (estimateData.fileFlg === '0') { + alert(getMessage('estimate.detail.save.alertMsg')) + flag = false + } + } }) - return result - } catch (error) { - console.error('Failed to submit estimate:', error) - throw error + } + if (flag) { + //1. 첨부파일 저장 + const formData = new FormData() + formData.append('file', estimateData.fileList) + formData.append('objectNo', estimateData.objectNo) + formData.append('planNo', estimateData.planNo) + formData.append('category', '10') + formData.append('userId', estimateData.userId) + for (const value of formData.values()) { + console.log('formData::', value) + } + + await promisePost({ url: '/api/file/fileUpload', data: formData }).then((res) => { + console.log('파일저장결과::::::::::', res) + }) + + //2. 상세데이터 저장 + + console.log('상세저장시작!!') + return + try { + const result = await promisePost({ + url: ESTIMATE_API_ENDPOINT, + data: estimateData, + }) + return result + } catch (error) { + console.error('Failed to submit estimate:', error) + throw error + } } } diff --git a/src/locales/ja.json b/src/locales/ja.json index 05ab09cf..8e32a8a4 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -818,7 +818,7 @@ "estimate.detail.estimateType": "注文分類", "estimate.detail.roofCns": "屋根材・仕様施工", "estimate.detail.remarks": "備考", - "estimate.detail.nextSubmit": "後日資料提出", + "estimate.detail.fileFlg": "後日資料提出", "estimate.detail.header.fileList1": "ファイル添付", "estimate.detail.fileList.btn": "ファイル選択", "estimate.detail.header.fileList2": "添付ファイル一覧", @@ -835,11 +835,20 @@ "estimate.detail.sepcialEstimateProductInfo.calcFormula1": "(モジュール容量 × 数量)÷1000", "estimate.detail.sepcialEstimateProductInfo.calcFormula2": "PKG単価 (W)×PKG容量(W)", "estimate.detail.header.showPrice": "価格表示", - "estimate.detail.showPrice.btn1": "Pricing", + "estimate.detail.header.unitPrice": "定価", + "estimate.detail.showPrice.pricingBtn": "Pricing", "estimate.detail.showPrice.description1": "製品価格 OPEN", "estimate.detail.showPrice.description2": "追加, 変更資材", "estimate.detail.showPrice.description3": "添付必須", "estimate.detail.showPrice.description4": "クリックして製品の特異性を確認する", "estimate.detail.showPrice.btn2": "製品を追加", - "estimate.detail.showPrice.btn3": "製品削除" + "estimate.detail.showPrice.btn3": "製品削除", + "estimate.detail.itemTableHeader.col1": "アイテム", + "estimate.detail.itemTableHeader.col2": "品番", + "estimate.detail.itemTableHeader.col3": "型板", + "estimate.detail.itemTableHeader.col4": "数量", + "estimate.detail.itemTableHeader.col5": "単位", + "estimate.detail.itemTableHeader.col6": "単価", + "estimate.detail.itemTableHeader.col7": "金額 (税別別)", + "estimate.detail.save.alertMsg": "ファイル添付が必須のアイテムがあります。ファイルを添付するか、後日添付をチェックしてください." } diff --git a/src/locales/ko.json b/src/locales/ko.json index d8cef240..30b3f130 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -824,7 +824,7 @@ "estimate.detail.estimateType": "주문분류", "estimate.detail.roofCns": "지붕재・사양시공", "estimate.detail.remarks": "비고", - "estimate.detail.nextSubmit": "후일자료제출", + "estimate.detail.fileFlg": "후일자료제출", "estimate.detail.header.fileList1": "파일첨부", "estimate.detail.fileList.btn": "파일선택", "estimate.detail.header.fileList2": "첨부파일 목록", @@ -841,11 +841,20 @@ "estimate.detail.sepcialEstimateProductInfo.calcFormula1": "(모듈수량 * 수량)÷100", "estimate.detail.sepcialEstimateProductInfo.calcFormula2": "PKG단가(W) * PKG용량(W)", "estimate.detail.header.showPrice": "가격표시", - "estimate.detail.showPrice.btn1": "Pricing", + "estimate.detail.header.unitPrice": "정가", + "estimate.detail.showPrice.pricingBtn": "Pricing", "estimate.detail.showPrice.description1": "제품 가격 OPEN", "estimate.detail.showPrice.description2": "추가, 변경 자재", "estimate.detail.showPrice.description3": "첨부필수", "estimate.detail.showPrice.description4": "클릭하여 제품 특이사항 확인", "estimate.detail.showPrice.btn2": "제품추가", - "estimate.detail.showPrice.btn3": "제품삭제" + "estimate.detail.showPrice.btn3": "제품삭제", + "estimate.detail.itemTableHeader.col1": "Item", + "estimate.detail.itemTableHeader.col2": "품번", + "estimate.detail.itemTableHeader.col3": "형명", + "estimate.detail.itemTableHeader.col4": "수량", + "estimate.detail.itemTableHeader.col5": "단위", + "estimate.detail.itemTableHeader.col6": "단가", + "estimate.detail.itemTableHeader.col7": "금액(부가세별도)", + "estimate.detail.save.alertMsg": "파일첨부가 필수인 아이템이 있습니다. 파일을 첨부하거나 후일첨부를 체크해주십시오." } From 223994c2dbeda0fb4d652e0dac7f60344619bc2a Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Thu, 7 Nov 2024 18:15:13 +0900 Subject: [PATCH 30/51] =?UTF-8?q?fix:=20=EB=8F=99=EC=9D=BC=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=20=EC=97=85=EB=A1=9C=EB=93=9C=20=EC=8B=9C=EB=8F=84?= =?UTF-8?q?=EC=8B=9C=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20=EB=B0=9C=EC=83=9D=20?= =?UTF-8?q?=EC=95=88=EB=90=98=EB=8D=98=20=EB=AC=B8=EC=A0=9C=20=ED=95=B4?= =?UTF-8?q?=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/estimate/EstimateFileUploader.jsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/estimate/EstimateFileUploader.jsx b/src/components/estimate/EstimateFileUploader.jsx index c2bccb22..dfc82d49 100644 --- a/src/components/estimate/EstimateFileUploader.jsx +++ b/src/components/estimate/EstimateFileUploader.jsx @@ -27,6 +27,7 @@ export default function EstimateFileUploader({ uploadFiles, setUploadFiles }) { // if (res.data > 0) setUploadFiles([...files, { name: e.target.files[0].name, id: uuidv4() }]) // }) setUploadFiles([...uploadFiles, { data: e.target.files[0], id: uuidv4() }]) + e.target.value = '' } const deleteFile = (id) => { From 23681ee3d7c78999e1ac6fd16d0e370e79b124b7 Mon Sep 17 00:00:00 2001 From: basssy Date: Fri, 8 Nov 2024 10:12:06 +0900 Subject: [PATCH 31/51] =?UTF-8?q?=EA=B2=AC=EC=A0=81=EC=84=9C=20=EC=83=81?= =?UTF-8?q?=EC=84=B8=EC=97=90=EC=84=9C=20CanvasMenu.jsx=20=EB=B2=84?= =?UTF-8?q?=ED=8A=BC=20=EC=A0=95=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/floor-plan/CanvasMenu.jsx | 53 +++++++++++++++++-- .../estimate/useEstimateController.js | 3 +- src/locales/ja.json | 4 +- src/locales/ko.json | 4 +- 4 files changed, 58 insertions(+), 6 deletions(-) diff --git a/src/components/floor-plan/CanvasMenu.jsx b/src/components/floor-plan/CanvasMenu.jsx index 613db2bd..e3da458c 100644 --- a/src/components/floor-plan/CanvasMenu.jsx +++ b/src/components/floor-plan/CanvasMenu.jsx @@ -33,6 +33,7 @@ import useMenu from '@/hooks/common/useMenu' import { MENU } from '@/common/common' import { useEstimateController } from '@/hooks/floorPlan/estimate/useEstimateController' +import { estimateState } from '@/store/floorPlanObjectAtom' export default function CanvasMenu(props) { const { menuNumber, setMenuNumber } = props @@ -54,6 +55,7 @@ export default function CanvasMenu(props) { const { handleZoomClear, handleZoom } = useCanvasEvent() const { handleMenu } = useMenu() const { handleEstimateSubmit } = useEstimateController() + const estimateRecoilState = useRecoilValue(estimateState) const { getMessage } = useMessage() const { currentCanvasPlan, saveCanvas } = usePlan() @@ -138,6 +140,38 @@ export default function CanvasMenu(props) { addPopup(id, 1, , true) } + // 견적서 초기화 버튼 + const handleEstimateReset = () => { + // console.log('estimateRecoilState::', estimateRecoilState) + //objectNo, planNo + swalFire({ + //저장된 견적서 정보가 초기화되고, 도면정보가 반영됩니다. 정말로 초기화 하시겠습니까? + //물건정보 + text: getMessage('estimate.detail.reset.confirmMsg'), + type: 'confirm', + confirmFn: () => { + console.log('내용초기화 및 변경일시 갱신') + }, + denyFn: () => { + console.log('초기화하지 않음. 변경일시 갱신안함') + }, + }) + } + + /** + * 견적서 복사버튼 + * (견적서 번호(estimateRecoilState.docNo)가 생성된 이후 버튼 활성화 ) + * T01관리자 계정 및 1차판매점에게만 제공 + */ + + const handleEstimateCopy = () => { + // console.log('estimateRecoilState::', estimateRecoilState) + //objectNo, planNo + console.log('복사') + console.log('물건정보+도면+견적서를 모두 복사') + console.log('견적서 가격은 정가를 표시') + } + useEffect(() => { if (globalLocale === 'ko') { setAppMessageState(KO) @@ -228,7 +262,7 @@ export default function CanvasMenu(props) { {menuNumber === 5 && ( <>
- @@ -236,11 +270,24 @@ export default function CanvasMenu(props) { {getMessage('plan.menu.estimate.save')} - - diff --git a/src/hooks/floorPlan/estimate/useEstimateController.js b/src/hooks/floorPlan/estimate/useEstimateController.js index aeec4f1c..5a0c49e1 100644 --- a/src/hooks/floorPlan/estimate/useEstimateController.js +++ b/src/hooks/floorPlan/estimate/useEstimateController.js @@ -135,7 +135,7 @@ export const useEstimateController = (planNo) => { estimateData.itemList.map((row) => { if (row.fileUploadFlg === '1') { if (estimateData.fileFlg === '0') { - alert(getMessage('estimate.detail.save.alertMsg')) + alert(getMessage('estimate.detail.save.requiredMsg')) flag = false } } @@ -166,6 +166,7 @@ export const useEstimateController = (planNo) => { url: ESTIMATE_API_ENDPOINT, data: estimateData, }) + alert(getMessage('estimate.detail.save.alertMsg')) return result } catch (error) { console.error('Failed to submit estimate:', error) diff --git a/src/locales/ja.json b/src/locales/ja.json index 8e32a8a4..b5636db5 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -850,5 +850,7 @@ "estimate.detail.itemTableHeader.col5": "単位", "estimate.detail.itemTableHeader.col6": "単価", "estimate.detail.itemTableHeader.col7": "金額 (税別別)", - "estimate.detail.save.alertMsg": "ファイル添付が必須のアイテムがあります。ファイルを添付するか、後日添付をチェックしてください." + "estimate.detail.save.alertMsg": "保存されている見積書で製品を変更した場合、図面や回路には反映されません.", + "estimate.detail.save.requiredMsg": "ファイル添付が必須のアイテムがあります。ファイルを添付するか、後日添付をチェックしてください.", + "estimate.detail.reset.confirmMsg": "保存した見積書情報が初期化され、図面情報が反映されます。本当に初期化しますか?" } diff --git a/src/locales/ko.json b/src/locales/ko.json index 30b3f130..60dc6279 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -856,5 +856,7 @@ "estimate.detail.itemTableHeader.col5": "단위", "estimate.detail.itemTableHeader.col6": "단가", "estimate.detail.itemTableHeader.col7": "금액(부가세별도)", - "estimate.detail.save.alertMsg": "파일첨부가 필수인 아이템이 있습니다. 파일을 첨부하거나 후일첨부를 체크해주십시오." + "estimate.detail.save.alertMsg": "저장되었습니다. 견적서에서 제품을 변경할 경우, 도면 및 회로에 반영되지 않습니다.", + "estimate.detail.save.requiredMsg": "파일첨부가 필수인 아이템이 있습니다. 파일을 첨부하거나 후일첨부를 체크해주십시오.", + "estimate.detail.reset.confirmMsg": "저장된 견적서 정보가 초기화되고, 도면정보가 반영됩니다. 정말로 초기화 하시겠습니까?" } From de95bc7c61d528a986155aeb33419bb42f59674e Mon Sep 17 00:00:00 2001 From: leeyongjae Date: Fri, 8 Nov 2024 10:53:59 +0900 Subject: [PATCH 32/51] =?UTF-8?q?=EB=B0=9C=EC=A0=84=20=EC=8B=9C=EB=AC=BC?= =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=85=98=20api=20=EC=97=B0=EB=8F=99=20?= =?UTF-8?q?=EB=B0=8F=20=EC=85=8B=ED=8C=85=20=EA=B0=92=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/simulator/Simulator.jsx | 148 +++++++++---------------- 1 file changed, 53 insertions(+), 95 deletions(-) diff --git a/src/components/simulator/Simulator.jsx b/src/components/simulator/Simulator.jsx index 9e7768a1..d9eb6f49 100644 --- a/src/components/simulator/Simulator.jsx +++ b/src/components/simulator/Simulator.jsx @@ -4,14 +4,13 @@ import 'chart.js/auto' import { Bar } from 'react-chartjs-2' import dayjs from 'dayjs' -import { useEffect, useState } from 'react' +import { useEffect, useState, useRef } from 'react' import { useRecoilState, useRecoilValue } from 'recoil' import { floorPlanObjectState } from '@/store/floorPlanObjectAtom' import { useAxios } from '@/hooks/useAxios' import { useMessage } from '@/hooks/useMessage' import { usePlan } from '@/hooks/usePlan' -import { useCommonCode } from '@/hooks/common/useCommonCode' import { useCanvasMenu } from '@/hooks/common/useCanvasMenu' import { convertNumberToPriceDecimal, isEmptyArray } from '@/util/common-utils' @@ -20,6 +19,8 @@ export default function Simulator() { const { plans } = usePlan() const plan = plans.find((plan) => plan.isCurrent === true) + const chartRef = useRef(null) + // recoil 물건번호 const objectRecoil = useRecoilValue(floorPlanObjectState) const [objectNo, setObjectNo] = useState('') @@ -38,41 +39,14 @@ export default function Simulator() { const { get } = useAxios() const { getMessage } = useMessage() - // 공통코드 조회 - const { commonCode, findCommonCode } = useCommonCode() - const [prefCodeList, setPrefCodeList] = useState([]) // 도도부현 코드 - const [areaIdList, setAreaIdList] = useState([]) // 시뮬레이션 코드 - const [windSpeedList, setWindSpeedList] = useState([]) // 기준 풍속 공통코드 - - useEffect(() => { - const code1 = findCommonCode(202000) // 기준풍속 - if (code1 != null) { - setWindSpeedList(code1) - } - }, [commonCode]) - - const chartData = [ - Math.floor(Math.random() * 1000), - Math.floor(Math.random() * 2000), - Math.floor(Math.random() * 3000), - Math.floor(Math.random() * 4000), - Math.floor(Math.random() * 5000), - Math.floor(Math.random() * 6000), - Math.floor(Math.random() * 6000), - Math.floor(Math.random() * 5000), - Math.floor(Math.random() * 4000), - Math.floor(Math.random() * 3000), - Math.floor(Math.random() * 2000), - Math.floor(Math.random() * 1000), - ] - // 차트 관련 + const [chartData1, setChartData1] = useState([]) const data = { labels: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'], datasets: [ { label: 'kWh', - data: chartData, + data: chartData1.slice(0, 12), backgroundColor: [ 'rgba(255, 99, 132, 0.2)', @@ -133,48 +107,46 @@ export default function Simulator() { fetchObjectDetail(objectNo) } fetchSimulatorNotice() - }, [objectNo]) + }, [objectNo, plan]) // 물건 상세 정보 조회 const [objectDetail, setObjectDetail] = useState({}) - const fetchObjectDetail = async (objectNo) => { - const apiUrl = `/api/object/${objectNo}/detail` - const resultData = await get({ url: apiUrl }) - - if (resultData) { - if (resultData.prefId) { - get({ url: '/api/object/prefecture/list' }).then((res) => { - if (!isEmptyArray(res)) { - setPrefCodeList(res) - } - }) - get({ url: `/api/object/prefecture/${resultData.prefId}/list` }).then((res) => { - if (!isEmptyArray(res)) { - setAreaIdList(res) - } - }) - } - setObjectDetail(resultData) - } - } - // 모듈배치정보 조회 const [moduleInfoList, setModuleInfoList] = useState([]) // 파워컨디셔너 조회 const [pcsInfoList, setPcsInfoList] = useState([]) + const fetchObjectDetail = async (objectNo) => { + const apiUrl = `/api/pwrGnrSimulation/calculations?objectNo=${objectNo}&planNo=${plan?.id}` + const resultData = await get({ url: apiUrl }) + if (resultData) { + console.log(resultData) + setObjectDetail(resultData) + if (resultData.frcPwrGnrList) { + setChartData1(resultData.frcPwrGnrList) + } + if (resultData.pcsList) { + setPcsInfoList(resultData.pcsList) + } + if (resultData.roofModuleList) { + setModuleInfoList(resultData.roofModuleList) + } + } + } + // 시뮬레이션 안내사항 조회 const [content, setContent] = useState('') const fetchSimulatorNotice = async () => { - const resultData = '1234123\r\n12\r\n3\r\n123\r\n12\r\n312\r\n312\r\n3123123123123\r\n\r\nㅅㄷㄴㅅ\r\nㅁㅅㄷㄴㅁㅅㄴㅁㅅㄴㅅ' - if (resultData) { - setContent(resultData.replaceAll('\n', '
')) - } else { - setContent(getMessage('common.message.no.data')) - } + get({ url: '/api/pwrGnrSimulation/guideInfo' }).then((res) => { + if (res.data) { + setContent(res.data.replaceAll('\n', '
')) + } else { + setContent(getMessage('common.message.no.data')) + } + }) } return ( @@ -187,56 +159,45 @@ export default function Simulator() {
{getMessage('simulator.title.sub1')}
- {objectNo} (Plan No: {plan?.id}) + {objectDetail.objectNo} (Plan No: {objectDetail.planNo})
{/* 작성일 */}
{getMessage('simulator.title.sub2')}
-
{`${dayjs(objectDetail.lastEditDatetime).format('YYYY.MM.DD')}`}
+
{`${dayjs(objectDetail.drawingEstimateCreateDate).format('YYYY.MM.DD')}`}
{/* 시스템용량 */}
{getMessage('simulator.title.sub3')}
-
??? kW
+
{convertNumberToPriceDecimal(objectDetail.capacity)}kW
{/* 연간예측발전량 */}
{getMessage('simulator.title.sub4')}
-
???
+
{convertNumberToPriceDecimal(objectDetail.anlFrcsGnrt)}
{/* 도도부현 */}
{getMessage('simulator.title.sub5')}
-
- {prefCodeList.map((prefCode) => (prefCode.prefId === objectDetail.prefId ? prefCode.prefName : ''))} - {` `} - {objectDetail.address} -
+
{objectDetail.prefName}
{/* 일사량 관측지점 */}
{getMessage('simulator.title.sub6')}
-
- {areaIdList.map((areaCode) => (areaCode.areaId === objectDetail.areaId ? areaCode.prefName : ''))} -
+
{objectDetail.areaName}
{/* 적설조건 */}
{getMessage('simulator.title.sub7')}
-
- {objectDetail.verticalSnowCover} - {objectDetail.verticalSnowCover && 'cm'} -
+
{objectDetail.snowfall}
{/* 풍속조건 */}
{getMessage('simulator.title.sub8')}
-
- {windSpeedList.map((windSpeed) => (windSpeed.clCode === objectDetail.standardWindSpeedId ? windSpeed.clCodeNm : ''))} -
+
{objectDetail.standardWindSpeedId}
@@ -246,7 +207,7 @@ export default function Simulator() {
- +
@@ -274,12 +235,7 @@ export default function Simulator() { - - {chartData.map((data) => ( - {convertNumberToPriceDecimal(data)} - ))} - {convertNumberToPriceDecimal(chartData.reduce((a, b) => a + b))} - + {chartData1.length > 0 && chartData1.map((data) => {convertNumberToPriceDecimal(data)})}
@@ -303,19 +259,19 @@ export default function Simulator() { moduleInfoList.map((moduleInfo) => { return ( <> - + {/* 지붕면 */} - 西南西1 + {moduleInfo.roofSurface} {/* 경사각 */} - 0.3寸 + {convertNumberToPriceDecimal(moduleInfo.slope)}寸 {/* 방위각(도) */} - 81 + {convertNumberToPriceDecimal(moduleInfo.angle)} {/* 태양전지모듈 */} -
Re.RISE-G2 415
+
{moduleInfo.itemNo}
{/* 매수 */} - 20 + {moduleInfo.amount} ) @@ -330,7 +286,9 @@ export default function Simulator() { {moduleInfoList.length > 0 && (
{getMessage('simulator.table.sub6')}
-
0
+
+ {moduleInfoList.reduce((acc, moduleInfo) => convertNumberToPriceDecimal(Number(acc) + Number(moduleInfo.amount)), 0)} +
)}
@@ -349,13 +307,13 @@ export default function Simulator() { pcsInfoList.map((pcsInfo) => { return ( <> - + {/* 파워컨디셔너 */} -
HQJP-MA55-3
+
{pcsInfo.itemNo}
{/* 대 */} - 2 + {pcsInfo.amount} ) From fd9b723523e219586f438e550972573b2bd69f70 Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Fri, 8 Nov 2024 11:25:58 +0900 Subject: [PATCH 33/51] =?UTF-8?q?=EB=94=94=EC=8A=A4=ED=94=8C=EB=A0=88?= =?UTF-8?q?=EC=9D=B4=20=EC=84=A4=EC=A0=95=20-=20=EC=B9=98=EC=88=98?= =?UTF-8?q?=ED=91=9C=EC=8B=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/fabric/QPolygon.js | 6 ++--- src/hooks/option/useCanvasSetting.js | 36 ++++++++++++++++++++++++++-- src/hooks/usePolygon.js | 5 ++-- src/store/settingAtom.js | 1 + 4 files changed, 39 insertions(+), 9 deletions(-) diff --git a/src/components/fabric/QPolygon.js b/src/components/fabric/QPolygon.js index d1f97e0e..a248412e 100644 --- a/src/components/fabric/QPolygon.js +++ b/src/components/fabric/QPolygon.js @@ -790,7 +790,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { setViewLengthText(isView) { this.canvas ?.getObjects() - .filter((obj) => obj.name === 'lengthText' && obj.parent === this) + .filter((obj) => obj.name === 'lengthText' && obj.parentId === this.id) .forEach((text) => { text.set({ visible: isView }) }) @@ -803,9 +803,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { this.scaleY = scale this.addLengthText() }, - divideLine() { - // splitPolygonWithLines(this) - }, + calcOriginCoords() { const points = this.points const minX = Math.min(...points.map((p) => p.x)) diff --git a/src/hooks/option/useCanvasSetting.js b/src/hooks/option/useCanvasSetting.js index 02691887..549cc9a4 100644 --- a/src/hooks/option/useCanvasSetting.js +++ b/src/hooks/option/useCanvasSetting.js @@ -5,7 +5,7 @@ import { globalLocaleStore } from '@/store/localeAtom' import { useMessage } from '@/hooks/useMessage' import { useAxios } from '@/hooks/useAxios' import { useSwal } from '@/hooks/useSwal' -import { settingModalFirstOptionsState, settingModalSecondOptionsState } from '@/store/settingAtom' +import { corridorDimensionSelector, settingModalFirstOptionsState, settingModalSecondOptionsState } from '@/store/settingAtom' import { setSurfaceShapePattern } from '@/util/canvas-util' import { POLYGON_TYPE } from '@/common/common' @@ -17,6 +17,8 @@ export function useCanvasSetting() { const { option1, option2, dimensionDisplay } = settingModalFirstOptions const { option3, option4 } = settingModalSecondOptions + const corridorDimension = useRecoilValue(corridorDimensionSelector) + const globalLocaleState = useRecoilValue(globalLocaleStore) const { get, post } = useAxios(globalLocaleState) const { getMessage } = useMessage() @@ -27,6 +29,36 @@ export function useCanvasSetting() { const [objectNo, setObjectNo] = useState('test123240912001') // 이후 삭제 필요 + useEffect(() => { + if (!canvas) { + return + } + const { column } = corridorDimension + const lengthTexts = canvas.getObjects().filter((obj) => obj.name === 'lengthText') + switch (column) { + case 'corridorDimension': + lengthTexts.forEach((obj) => { + if (obj.planeSize) { + obj.set({ text: obj.planeSize.toString() }) + } + }) + break + case 'realDimension': + lengthTexts.forEach((obj) => { + if (obj.actualSize) { + obj.set({ text: obj.actualSize.toString() }) + } + }) + break + case 'noneDimension': + lengthTexts.forEach((obj) => { + obj.set({ text: '' }) + }) + break + } + canvas.renderAll() + }, [corridorDimension]) + useEffect(() => { console.log('useCanvasSetting useEffect 실행1') fetchSettings() @@ -257,7 +289,7 @@ export function useCanvasSetting() { optionName = ['7'] break case 'flowDisplay': //흐름방향 표시 - optionName = ['arrow'] + optionName = ['arrow', 'flowText'] break case 'trestleDisplay': //가대 표시 optionName = ['8'] diff --git a/src/hooks/usePolygon.js b/src/hooks/usePolygon.js index 9ea8b3b7..699b4f09 100644 --- a/src/hooks/usePolygon.js +++ b/src/hooks/usePolygon.js @@ -693,8 +693,7 @@ export const usePolygon = () => { } } }) - - const direction = newRoofs.length === 1 ? polygon.direction : representLine.direction + const direction = polygon.direction ?? representLine.direction const polygonDirection = polygon.direction switch (direction) { @@ -723,7 +722,7 @@ export const usePolygon = () => { originY: 'center', selectable: true, defense: defense, - direction: newRoofs.length === 1 ? polygonDirection : defense, + direction: polygonDirection ?? defense, pitch: pitch, }) diff --git a/src/store/settingAtom.js b/src/store/settingAtom.js index fede515e..869cc004 100644 --- a/src/store/settingAtom.js +++ b/src/store/settingAtom.js @@ -185,6 +185,7 @@ export const corridorDimensionSelector = selector({ const settingModalFirstOptions = get(settingModalFirstOptionsState) return settingModalFirstOptions.dimensionDisplay.find((option) => option.selected) }, + dangerouslyAllowMutability: true, }) // 디스플레이 설정 - 화면 표시 From 8cd833e08f9bc7aae29f7dd071f738d33b138ee7 Mon Sep 17 00:00:00 2001 From: basssy Date: Fri, 8 Nov 2024 12:06:48 +0900 Subject: [PATCH 34/51] =?UTF-8?q?=EA=B2=AC=EC=A0=81=EC=84=9C=20=EC=83=81?= =?UTF-8?q?=EC=84=B8=ED=99=94=EB=A9=B4=EB=B2=84=ED=8A=BC=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=A0=95=EC=9D=98=20CanvasMenu.jsx=20=ED=8C=9D?= =?UTF-8?q?=EC=97=85=EC=9E=91=EC=97=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/estimate/Estimate.jsx | 2 +- .../estimate/popup/DocDownOptionPop.jsx | 255 ++++++++++++++++++ src/components/floor-plan/CanvasMenu.jsx | 7 +- src/locales/ja.json | 18 ++ src/locales/ko.json | 18 ++ 5 files changed, 298 insertions(+), 2 deletions(-) create mode 100644 src/components/estimate/popup/DocDownOptionPop.jsx diff --git a/src/components/estimate/Estimate.jsx b/src/components/estimate/Estimate.jsx index 87aa3397..442c597b 100644 --- a/src/components/estimate/Estimate.jsx +++ b/src/components/estimate/Estimate.jsx @@ -539,7 +539,7 @@ export default function Estimate({ params }) { return (
{row.codeNm}
-
{row.remarks}
+
) } diff --git a/src/components/estimate/popup/DocDownOptionPop.jsx b/src/components/estimate/popup/DocDownOptionPop.jsx new file mode 100644 index 00000000..0c859c59 --- /dev/null +++ b/src/components/estimate/popup/DocDownOptionPop.jsx @@ -0,0 +1,255 @@ +'use client' +import { useState } from 'react' +import { useMessage } from '@/hooks/useMessage' +import { useAxios } from '@/hooks/useAxios' +import { useRecoilValue } from 'recoil' +import { floorPlanObjectState } from '@/store/floorPlanObjectAtom' + +export default function DocDownOptionPop({ planNo, setEstimatePopupOpen }) { + // console.log('플랜번호::::::::::::', planNo) + const { getMessage } = useMessage() + const { promiseGet } = useAxios() + + //다운로드 파일 EXCEL + const [schUnitPriceFlg, setSchUnitPriceFlg] = useState('0') + + //견적제출서 표시명 + const [schDisplayFlg, setSchSchDisplayFlg] = useState('0') + //가대 중량표 포함 + const [schWeightFlg, setSchWeightFlg] = useState('0') + //도면/시뮬레이션 파일 포함 + const [schDrawingFlg, setSchDrawingFlg] = useState('0') + + // recoil 물건번호 + const objectRecoil = useRecoilValue(floorPlanObjectState) + + //문서 다운로드 + const handleFileDown = async () => { + // console.log('물건번호:::', objectRecoil.floorPlanObjectNo) + // console.log('planNo::', planNo) + // 고른 옵션값들 + //0 : 견적가 Excel 1 : 정가용Excel 2: 견적가 PDF 3 :정가용PDF + // console.log(schUnitPriceFlg) + // console.log(schDisplayFlg) + // console.log(schWeightFlg) + // console.log(schDrawingFlg) + const url = '/api/estimate/excel-download' + const params = {} + const options = { responseType: 'blob' } + } + + return ( +
+
+
+
+

{getMessage('estimate.detail.docPopup.title')}

+ +
+
+
+
{getMessage('estimate.detail.docPopup.explane')}
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ {getMessage('estimate.detail.docPopup.schUnitPriceFlg')} + * + +
+
+ { + setSchUnitPriceFlg(e.target.value) + }} + /> + +
+
+ { + setSchUnitPriceFlg(e.target.value) + }} + /> + +
+
+ { + setSchUnitPriceFlg(e.target.value) + }} + /> + +
+
+ { + setSchUnitPriceFlg(e.target.value) + }} + /> + +
+
+
+ {getMessage('estimate.detail.docPopup.schDisplayFlg')} * + +
+
+ { + setSchSchDisplayFlg(e.target.value) + }} + /> + +
+
+ { + setSchSchDisplayFlg(e.target.value) + }} + /> + +
+
+
+ {getMessage('estimate.detail.docPopup.schWeightFlg')} * + +
+
+ { + setSchWeightFlg(e.target.value) + }} + /> + +
+
+ { + setSchWeightFlg(e.target.value) + }} + /> + +
+
+
{getMessage('estimate.detail.docPopup.schDrawingFlg')} +
+
+ { + setSchDrawingFlg(e.target.value) + }} + /> + +
+
+ { + setSchDrawingFlg(e.target.value) + }} + /> + +
+
+
+
+
+
+ + +
+
+
+
+
+ ) +} diff --git a/src/components/floor-plan/CanvasMenu.jsx b/src/components/floor-plan/CanvasMenu.jsx index e3da458c..e544dbec 100644 --- a/src/components/floor-plan/CanvasMenu.jsx +++ b/src/components/floor-plan/CanvasMenu.jsx @@ -34,6 +34,7 @@ import { MENU } from '@/common/common' import { useEstimateController } from '@/hooks/floorPlan/estimate/useEstimateController' import { estimateState } from '@/store/floorPlanObjectAtom' +import DocDownOptionPop from '../estimate/popup/DocDownOptionPop' export default function CanvasMenu(props) { const { menuNumber, setMenuNumber } = props @@ -54,8 +55,10 @@ export default function CanvasMenu(props) { const canvas = useRecoilValue(canvasState) const { handleZoomClear, handleZoom } = useCanvasEvent() const { handleMenu } = useMenu() + const { handleEstimateSubmit } = useEstimateController() const estimateRecoilState = useRecoilValue(estimateState) + const [estimatePopupOpen, setEstimatePopupOpen] = useState(false) const { getMessage } = useMessage() const { currentCanvasPlan, saveCanvas } = usePlan() @@ -262,7 +265,7 @@ export default function CanvasMenu(props) { {menuNumber === 5 && ( <>
- @@ -313,6 +316,8 @@ export default function CanvasMenu(props) {
{(menuNumber === 2 || menuNumber === 3 || menuNumber === 4) && }
+ {/* 견적서(menuNumber=== 5) 상세화면인경우 문서다운로드 팝업 */} + {estimatePopupOpen && }
) } diff --git a/src/locales/ja.json b/src/locales/ja.json index b5636db5..6fe9444d 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -850,6 +850,24 @@ "estimate.detail.itemTableHeader.col5": "単位", "estimate.detail.itemTableHeader.col6": "単価", "estimate.detail.itemTableHeader.col7": "金額 (税別別)", + "estimate.detail.docPopup.title": "ドキュメントダウンロードオプションの設定", + "estimate.detail.docPopup.explane": "ダウンロードする文書のオプションを選択したら、 [文書のダウンロード]ボタンをクリックします.", + "estimate.detail.docPopup.schUnitPriceFlg": "ダウンロードファイル", + "estimate.detail.docPopup.schUnitPriceFlg.schUnitPriceFlg0": "見積もり Excel", + "estimate.detail.docPopup.schUnitPriceFlg.schUnitPriceFlg1": "定価用 Excel", + "estimate.detail.docPopup.schUnitPriceFlg.schUnitPriceFlg2": "見積もり PDF", + "estimate.detail.docPopup.schUnitPriceFlg.schUnitPriceFlg3": "定価用 PDF", + "estimate.detail.docPopup.schDisplayFlg": "見積提出先表示名", + "estimate.detail.docPopup.schDisplayFlg.schDisplayFlg0": "販売店名", + "estimate.detail.docPopup.schDisplayFlg.schDisplayFlg1": "案件名", + "estimate.detail.docPopup.schWeightFlg": "架台重量表を含む", + "estimate.detail.docPopup.schWeightFlg.schWeightFlg0": "含む", + "estimate.detail.docPopup.schWeightFlg.schWeightFlg1": "含まない", + "estimate.detail.docPopup.schDrawingFlg": "図面/シミュレーションファイルを含む", + "estimate.detail.docPopup.schDrawingFlg.schDrawingFlg0": "含む", + "estimate.detail.docPopup.schDrawingFlg.schDrawingFlg1": "含まない", + "estimate.detail.docPopup.close": "閉じる", + "estimate.detail.docPopup.docDownload": "文書のダウンロード", "estimate.detail.save.alertMsg": "保存されている見積書で製品を変更した場合、図面や回路には反映されません.", "estimate.detail.save.requiredMsg": "ファイル添付が必須のアイテムがあります。ファイルを添付するか、後日添付をチェックしてください.", "estimate.detail.reset.confirmMsg": "保存した見積書情報が初期化され、図面情報が反映されます。本当に初期化しますか?" diff --git a/src/locales/ko.json b/src/locales/ko.json index 60dc6279..f8d6d28b 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -856,6 +856,24 @@ "estimate.detail.itemTableHeader.col5": "단위", "estimate.detail.itemTableHeader.col6": "단가", "estimate.detail.itemTableHeader.col7": "금액(부가세별도)", + "estimate.detail.docPopup.title": "문서다운로드 옵션설정", + "estimate.detail.docPopup.explane": "다운로드할 문서 옵션을 선택한 후 문서 다운로드 버튼을 클릭합니다.", + "estimate.detail.docPopup.schUnitPriceFlg": "다운로드 파일", + "estimate.detail.docPopup.schUnitPriceFlg.schUnitPriceFlg0": "견적가 Excel", + "estimate.detail.docPopup.schUnitPriceFlg.schUnitPriceFlg1": "정가용 Excel", + "estimate.detail.docPopup.schUnitPriceFlg.schUnitPriceFlg2": "견적가 PDF", + "estimate.detail.docPopup.schUnitPriceFlg.schUnitPriceFlg3": "정가용 PDF", + "estimate.detail.docPopup.schDisplayFlg": "견적제출서 표시명", + "estimate.detail.docPopup.schDisplayFlg.schDisplayFlg0": "판매점명", + "estimate.detail.docPopup.schDisplayFlg.schDisplayFlg1": "안건명", + "estimate.detail.docPopup.schWeightFlg": "가대 중량표 포함", + "estimate.detail.docPopup.schWeightFlg.schWeightFlg0": "포함", + "estimate.detail.docPopup.schWeightFlg.schWeightFlg1": "미포함", + "estimate.detail.docPopup.schDrawingFlg": "도면/시뮬레이션 파일 포함", + "estimate.detail.docPopup.schDrawingFlg.schDrawingFlg0": "포함", + "estimate.detail.docPopup.schDrawingFlg.schDrawingFlg1": "미포함", + "estimate.detail.docPopup.close": "닫기", + "estimate.detail.docPopup.docDownload": "문서 다운로드", "estimate.detail.save.alertMsg": "저장되었습니다. 견적서에서 제품을 변경할 경우, 도면 및 회로에 반영되지 않습니다.", "estimate.detail.save.requiredMsg": "파일첨부가 필수인 아이템이 있습니다. 파일을 첨부하거나 후일첨부를 체크해주십시오.", "estimate.detail.reset.confirmMsg": "저장된 견적서 정보가 초기화되고, 도면정보가 반영됩니다. 정말로 초기화 하시겠습니까?" From a4adf4dd2fb42e63c6388ba78543cb00f72e18f8 Mon Sep 17 00:00:00 2001 From: leeyongjae Date: Fri, 8 Nov 2024 13:05:15 +0900 Subject: [PATCH 35/51] =?UTF-8?q?=EB=B0=9C=EC=A0=84=20=EC=8B=9C=EB=AC=BC?= =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=85=98=20=EB=8B=A4=EA=B5=AD=EC=96=B4=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/simulator/Simulator.jsx | 23 ++++++++++++++++------- src/locales/ja.json | 22 +++++++++++++++++++++- src/locales/ko.json | 22 +++++++++++++++++++++- 3 files changed, 58 insertions(+), 9 deletions(-) diff --git a/src/components/simulator/Simulator.jsx b/src/components/simulator/Simulator.jsx index d9eb6f49..c909ca17 100644 --- a/src/components/simulator/Simulator.jsx +++ b/src/components/simulator/Simulator.jsx @@ -5,7 +5,7 @@ import { Bar } from 'react-chartjs-2' import dayjs from 'dayjs' import { useEffect, useState, useRef } from 'react' -import { useRecoilState, useRecoilValue } from 'recoil' +import { useRecoilValue } from 'recoil' import { floorPlanObjectState } from '@/store/floorPlanObjectAtom' import { useAxios } from '@/hooks/useAxios' @@ -13,7 +13,7 @@ import { useMessage } from '@/hooks/useMessage' import { usePlan } from '@/hooks/usePlan' import { useCanvasMenu } from '@/hooks/common/useCanvasMenu' -import { convertNumberToPriceDecimal, isEmptyArray } from '@/util/common-utils' +import { convertNumberToPriceDecimal } from '@/util/common-utils' export default function Simulator() { const { plans } = usePlan() @@ -40,13 +40,13 @@ export default function Simulator() { const { getMessage } = useMessage() // 차트 관련 - const [chartData1, setChartData1] = useState([]) + const [chartData, setChartData] = useState([]) const data = { labels: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'], datasets: [ { label: 'kWh', - data: chartData1.slice(0, 12), + data: chartData.slice(0, 12), backgroundColor: [ 'rgba(255, 99, 132, 0.2)', @@ -122,10 +122,9 @@ export default function Simulator() { const apiUrl = `/api/pwrGnrSimulation/calculations?objectNo=${objectNo}&planNo=${plan?.id}` const resultData = await get({ url: apiUrl }) if (resultData) { - console.log(resultData) setObjectDetail(resultData) if (resultData.frcPwrGnrList) { - setChartData1(resultData.frcPwrGnrList) + setChartData(resultData.frcPwrGnrList) } if (resultData.pcsList) { setPcsInfoList(resultData.pcsList) @@ -235,7 +234,17 @@ export default function Simulator() { - {chartData1.length > 0 && chartData1.map((data) => {convertNumberToPriceDecimal(data)})} + {chartData.length > 0 ? ( + + {chartData.map((data) => ( + {convertNumberToPriceDecimal(data)} + ))} + + ) : ( + + {getMessage('common.message.no.data')} + + )}
diff --git a/src/locales/ja.json b/src/locales/ja.json index 6fe9444d..2d0c2871 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -870,5 +870,25 @@ "estimate.detail.docPopup.docDownload": "文書のダウンロード", "estimate.detail.save.alertMsg": "保存されている見積書で製品を変更した場合、図面や回路には反映されません.", "estimate.detail.save.requiredMsg": "ファイル添付が必須のアイテムがあります。ファイルを添付するか、後日添付をチェックしてください.", - "estimate.detail.reset.confirmMsg": "保存した見積書情報が初期化され、図面情報が反映されます。本当に初期化しますか?" + "estimate.detail.reset.confirmMsg": "保存した見積書情報が初期化され、図面情報が反映されます。本当に初期化しますか?", + "simulator.title.sub1": "物件番号", + "simulator.title.sub2": "作成日", + "simulator.title.sub3": "システム容量", + "simulator.title.sub4": "年間予測発電量", + "simulator.title.sub5": "都道府県", + "simulator.title.sub6": "日射量観測地点", + "simulator.title.sub7": "積雪条件", + "simulator.title.sub8": "風速条件", + "simulator.title.sub9": "以下", + "simulator.table.sub1": "屋根面", + "simulator.table.sub2": "傾斜角", + "simulator.table.sub3": "方位角(度)", + "simulator.table.sub4": "太陽電池モジュール", + "simulator.table.sub5": "枚数", + "simulator.table.sub6": "合計", + "simulator.table.sub7": "パワーコンディショナー", + "simulator.table.sub8": "台", + "simulator.table.sub9": "予測発電量 (kWh)", + "simulator.notice.sub1": "Hanwha Japan 年間発電量", + "simulator.notice.sub2": "シミュレーション案内事項" } diff --git a/src/locales/ko.json b/src/locales/ko.json index f8d6d28b..55e1becb 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -876,5 +876,25 @@ "estimate.detail.docPopup.docDownload": "문서 다운로드", "estimate.detail.save.alertMsg": "저장되었습니다. 견적서에서 제품을 변경할 경우, 도면 및 회로에 반영되지 않습니다.", "estimate.detail.save.requiredMsg": "파일첨부가 필수인 아이템이 있습니다. 파일을 첨부하거나 후일첨부를 체크해주십시오.", - "estimate.detail.reset.confirmMsg": "저장된 견적서 정보가 초기화되고, 도면정보가 반영됩니다. 정말로 초기화 하시겠습니까?" + "estimate.detail.reset.confirmMsg": "저장된 견적서 정보가 초기화되고, 도면정보가 반영됩니다. 정말로 초기화 하시겠습니까?", + "simulator.title.sub1": "물건번호", + "simulator.title.sub2": "작성일", + "simulator.title.sub3": "시스템 용량", + "simulator.title.sub4": "연간예측발전량", + "simulator.title.sub5": "도도부현", + "simulator.title.sub6": "일사량 관측지점", + "simulator.title.sub7": "적설조건", + "simulator.title.sub8": "풍속조건", + "simulator.title.sub9": "이하", + "simulator.table.sub1": "지붕면", + "simulator.table.sub2": "경사각", + "simulator.table.sub3": "방위각(도)", + "simulator.table.sub4": "태양전지모듈", + "simulator.table.sub5": "매수", + "simulator.table.sub6": "합계", + "simulator.table.sub7": "파워 컨디셔너", + "simulator.table.sub8": "대", + "simulator.table.sub9": "예측발전량 (kWh)", + "simulator.notice.sub1": "Hanwha Japan 연간 발전량", + "simulator.notice.sub2": "시뮬레이션 안내사항" } From 211a365bf8701d540847bfb5e1bb6269e8e90456 Mon Sep 17 00:00:00 2001 From: Jaeyoung Lee Date: Fri, 8 Nov 2024 13:46:57 +0900 Subject: [PATCH 36/51] =?UTF-8?q?=EB=A7=88=EB=A3=A8=20=EC=A7=80=EB=B6=95?= =?UTF-8?q?=20=EB=A7=88=EB=A3=A8=20=EB=B6=80=EB=B6=84=20=EC=98=A4=EB=A5=98?= =?UTF-8?q?=EC=97=90=20=EB=8C=80=ED=95=B4=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/useMode.js | 5 ++++ src/util/qpolygon-utils.js | 59 ++++++++++++++++++++------------------ 2 files changed, 36 insertions(+), 28 deletions(-) diff --git a/src/hooks/useMode.js b/src/hooks/useMode.js index 84c4fac6..ce7b8210 100644 --- a/src/hooks/useMode.js +++ b/src/hooks/useMode.js @@ -1782,8 +1782,13 @@ export function useMode() { } wall.lines.forEach((line, index) => { + const lineLength = Math.sqrt( + Math.pow(Math.round(Math.abs(line.x1 - line.x2) * 10), 2) + Math.pow(Math.round(Math.abs(line.y1 - line.y2) * 10), 2), + ) line.attributes.roofId = roof.id line.attributes.currentRoof = roof.lines[index].id + line.attributes.planeSize = lineLength + line.attributes.actualSize = lineLength }) setRoof(roof) diff --git a/src/util/qpolygon-utils.js b/src/util/qpolygon-utils.js index d84330e8..69102461 100644 --- a/src/util/qpolygon-utils.js +++ b/src/util/qpolygon-utils.js @@ -1,13 +1,6 @@ import { fabric } from 'fabric' import { QLine } from '@/components/fabric/QLine' -import { - calculateIntersection, - distanceBetweenPoints, - findClosestPoint, - getDegreeByChon, - getDirectionByPoint, - isPointOnLine, -} from '@/util/canvas-util' +import { calculateIntersection, distanceBetweenPoints, findClosestPoint, getDegreeByChon, getDirectionByPoint } from '@/util/canvas-util' import { QPolygon } from '@/components/fabric/QPolygon' import * as turf from '@turf/turf' @@ -1307,14 +1300,19 @@ const drawRidge = (roof, canvas) => { prevRoof = index === 0 ? wallLines[wallLines.length - 1] : wallLines[index - 1] nextRoof = index === wallLines.length - 1 ? wallLines[0] : index === wallLines.length ? wallLines[1] : wallLines[index + 1] - if (prevRoof.direction !== nextRoof.direction && currentWall.length <= currentRoof.length) { - ridgeRoof.push({ index: index, roof: currentRoof, length: currentRoof.length }) + const angle1 = calculateAngle(prevRoof.startPoint, prevRoof.endPoint) + const angle2 = calculateAngle(nextRoof.startPoint, nextRoof.endPoint) + + if (Math.abs(angle1 - angle2) === 180 && currentWall.attributes.planeSize <= currentRoof.attributes.planeSize) { + ridgeRoof.push({ index: index, roof: currentRoof, length: currentRoof.attributes.planeSize }) } }) // 지붕의 길이가 짧은 순으로 정렬 ridgeRoof.sort((a, b) => a.length - b.length) + console.log('ridgeRoof', ridgeRoof) + ridgeRoof.forEach((item) => { if (getMaxRidge(roofLines.length) > roof.ridges.length) { let index = item.index, @@ -1336,28 +1334,26 @@ const drawRidge = (roof, canvas) => { let xEqualInnerLines = anotherRoof.filter((roof) => roof.x1 === roof.x2 && isInnerLine(prevRoof, currentRoof, nextRoof, roof)), //x가 같은 내부선 yEqualInnerLines = anotherRoof.filter((roof) => roof.y1 === roof.y2 && isInnerLine(prevRoof, currentRoof, nextRoof, roof)) //y가 같은 내부선 - let ridgeBaseLength = Math.round((currentRoof.length / 2) * 10) / 10, // 지붕의 기반 길이 - ridgeMaxLength = Math.min(prevRoof.length, nextRoof.length), // 지붕의 최대 길이. 이전, 다음 벽 중 짧은 길이 - ridgeAcrossLength = Math.round((ridgeMaxLength - currentRoof.length) * 10) / 10 // 맞은편 벽까지의 길이 - 지붕의 기반 길이 + console.log('xEqualInnerLines', xEqualInnerLines, 'yEqualInnerLines', yEqualInnerLines) + let ridgeBaseLength = Math.round(currentRoof.attributes.planeSize / 2), // 지붕의 기반 길이 + ridgeMaxLength = Math.min(prevRoof.attributes.planeSize, nextRoof.attributes.planeSize), // 지붕의 최대 길이. 이전, 다음 벽 중 짧은 길이 + ridgeAcrossLength = Math.abs(ridgeMaxLength - currentRoof.attributes.planeSize) // 맞은편 벽까지의 길이 - 지붕의 기반 길이 let acrossRoof = anotherRoof .filter((roof) => { - if (roof.x1 === roof.x2) { - if ((nextRoof.direction === 'right' && roof.x1 > currentRoof.x1) || (nextRoof.direction === 'left' && roof.x1 < currentRoof.x1)) { - return roof - } - } - if (roof.y1 === roof.y2) { - if ((nextRoof.direction === 'top' && roof.y1 < currentRoof.y1) || (nextRoof.direction === 'bottom' && roof.y1 > currentRoof.y1)) { - return roof - } + const angle1 = calculateAngle(currentRoof.startPoint, currentRoof.endPoint) + const angle2 = calculateAngle(roof.startPoint, roof.endPoint) + if (Math.abs(angle1 - angle2) === 180) { + return roof } }) .reduce((prev, current) => { + console.log('prev', prev, 'current', current) + console.log('currentRoof', currentRoof) let hasBetweenRoof = false if (current.x1 === current.x2) { hasBetweenRoof = roofLines - .filter((roof) => roof !== current && roof !== currentRoof) + .filter((roof) => roof !== current) .some((line) => { let currentY2 = currentRoof.y2 if (yEqualInnerLines.length > 0) { @@ -1369,12 +1365,13 @@ const drawRidge = (roof, canvas) => { const isY2Between = (line.y2 > currentRoof.y1 && line.y2 < currentY2) || (line.y2 > currentY2 && line.y2 < currentRoof.y1) const isX1Between = (line.x1 > currentRoof.x1 && line.x1 < current.x1) || (line.x1 > currentRoof.x1 && line.x1 < current.x1) const isX2Between = (line.x2 > currentRoof.x1 && line.x2 < current.x1) || (line.x2 > currentRoof.x1 && line.x2 < current.x1) + return isY1Between && isY2Between && isX1Between && isX2Between }) } if (current.y1 === current.y2) { - hasBetweenRoof = wallLines - .filter((roof) => roof !== current && roof !== currentRoof) + hasBetweenRoof = roofLines + .filter((roof) => roof !== current) .some((line) => { let currentX2 = currentRoof.x2 if (xEqualInnerLines.length > 0) { @@ -1382,15 +1379,19 @@ const drawRidge = (roof, canvas) => { currentX2 = Math.abs(currentRoof.x1 - currentX2) < Math.abs(currentRoof.x1 - line.x1) ? currentX2 : line.x1 }) } + console.log('line :', line) const isX1Between = (line.x1 > currentRoof.x1 && line.x1 < currentX2) || (line.x1 > currentX2 && line.x1 < currentRoof.x1) const isX2Between = (line.x2 > currentRoof.x1 && line.x2 < currentX2) || (line.x2 > currentX2 && line.x2 < currentRoof.x1) const isY1Between = (line.y1 > currentRoof.y1 && line.y1 < current.y1) || (line.y1 > currentRoof.y1 && line.y1 < current.y1) const isY2Between = (line.y2 > currentRoof.y1 && line.y2 < current.y1) || (line.y2 > currentRoof.y1 && line.y2 < current.y1) + console.log('isX1Between', isX1Between, 'isX2Between', isX2Between, 'isY1Between', isY1Between, 'isY2Between', isY2Between) return isX1Between && isX2Between && isY1Between && isY2Between }) } + console.log('hasBetweenRoof', hasBetweenRoof) + if (prev !== undefined) { if (currentRoof.x1 === currentRoof.x2) { return Math.abs(currentRoof.y1 - prev.y1) > Math.abs(currentRoof.y1 - current.y1) ? prev : current @@ -1412,20 +1413,22 @@ const drawRidge = (roof, canvas) => { } } }, undefined) - if (acrossRoof !== undefined) { if (currentRoof.x1 === currentRoof.x2) { if (ridgeAcrossLength < Math.abs(currentRoof.x1 - acrossRoof.x1)) { - ridgeAcrossLength = Math.round((Math.round(Math.abs(currentRoof.x1 - acrossRoof.x1) * 10) / 10 - currentRoof.length) * 10) / 10 + ridgeAcrossLength = Math.round(Math.round(Math.abs(currentRoof.x1 - acrossRoof.x1) * 10) - currentRoof.attributes.planeSize) } } if (currentRoof.y1 === currentRoof.y2) { if (ridgeAcrossLength < Math.abs(currentRoof.y1 - acrossRoof.y1)) { - ridgeAcrossLength = Math.round((Math.round(Math.abs(currentRoof.y1 - acrossRoof.y1) * 10) / 10 - currentRoof.length) * 10) / 10 + ridgeAcrossLength = Math.round(Math.round(Math.abs(currentRoof.y1 - acrossRoof.y1) * 10) - currentRoof.attributes.planeSize) } } } + ridgeBaseLength = ridgeBaseLength / 10 + ridgeMaxLength = ridgeMaxLength / 10 + ridgeAcrossLength = ridgeAcrossLength / 10 if (ridgeBaseLength > 0 && ridgeMaxLength > 0 && ridgeAcrossLength > 0) { let ridgeLength = Math.min(ridgeMaxLength, ridgeAcrossLength) if (currentRoof.x1 === currentRoof.x2) { From c2808f88011e015f0d9b12a67f03f0fbf8d752f3 Mon Sep 17 00:00:00 2001 From: basssy Date: Fri, 8 Nov 2024 13:47:22 +0900 Subject: [PATCH 37/51] =?UTF-8?q?=EB=AC=BC=EA=B1=B4=20=EB=AA=A9=EB=A1=9D?= =?UTF-8?q?=20/=20=EC=83=81=EC=84=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/management/Stuff.jsx | 8 ++- src/components/management/StuffDetail.jsx | 66 ++++++++++++++++--- .../management/StuffSearchCondition.jsx | 34 +++++----- 3 files changed, 80 insertions(+), 28 deletions(-) diff --git a/src/components/management/Stuff.jsx b/src/components/management/Stuff.jsx index 58b1c002..fb7ecd76 100644 --- a/src/components/management/Stuff.jsx +++ b/src/components/management/Stuff.jsx @@ -190,9 +190,11 @@ export default function Stuff() { }) } - if (stuffSearch.schSelSaleStoreId !== '') { - fetchData() - } + //if (session.storeId === 'T01') { + fetchData() + //} else if (stuffSearch.schSelSaleStoreId !== '') { + //fetchData() + //} } else if (stuffSearchParams?.code === 'M') { const params = { saleStoreId: session?.storeId, diff --git a/src/components/management/StuffDetail.jsx b/src/components/management/StuffDetail.jsx index 61cdc1df..602c6354 100644 --- a/src/components/management/StuffDetail.jsx +++ b/src/components/management/StuffDetail.jsx @@ -59,7 +59,7 @@ export default function StuffDetail() { standardWindSpeedId: '', //기준풍속 verticalSnowCover: '', //수직적설량 coldRegionFlg: false, //한랭지대책시행(true : 1 / false : 0) - surfaceType: 'III・IV', //면조도구분(III・IV / Ⅱ) + surfaceType: 'Ⅲ・Ⅳ', //면조도구분(Ⅲ・Ⅳ / Ⅱ) saltAreaFlg: false, //염해지역용아이템사용 (true : 1 / false : 0) installHeight: '', //설치높이 conType: '0', //계약조건(잉여 / 전량) @@ -550,7 +550,7 @@ export default function StuffDetail() { //면조도구분 surfaceType null로 내려오면 셋팅 안하고 저장할때 필수값 체크하도록 // form.setValue('surfaceType', 'Ⅱ') - // form.setValue('surfaceType', 'III・IV') + // form.setValue('surfaceType', 'Ⅲ・Ⅳ') form.setValue('surfaceType', detailData.surfaceType) //염해지역용아이템사용 saltAreaFlg 1이면 true form.setValue('saltAreaFlg', detailData.saltAreaFlg === '1' ? true : false) @@ -872,6 +872,9 @@ export default function StuffDetail() { form.setValue('standardWindSpeedId', `WL_${info.windSpeed}`) form.setValue('verticalSnowCover', info.verticalSnowCover) form.setValue('surfaceType', info.surfaceType) + if (info.surfaceType === 'Ⅱ') { + form.setValue('saltAreaFlg', true) + } form.setValue('installHeight', info.installHeight) form.setValue('remarks', info.remarks) @@ -893,6 +896,15 @@ export default function StuffDetail() { form.setValue('standardWindSpeedId', info.windSpeed) } + //면조도구분surfaceType & 염해지역용아이템사용saltAreaFlg 컨트롤 + const handleRadioChange = (e) => { + if (e.target.value === 'Ⅱ') { + form.setValue('saltAreaFlg', true) + } else { + form.setValue('saltAreaFlg', false) + } + } + //receiveUser: '', //담당자 const _receiveUser = watch('receiveUser') //objectName: '', //물건명 @@ -1561,7 +1573,7 @@ export default function StuffDetail() { onChange={onSelectionChange2} getOptionLabel={(x) => x.saleStoreName} getOptionValue={(x) => x.saleStoreId} - isDisabled={otherSaleStoreList.length > 1 ? false : true} + isDisabled={otherSaleStoreList.length > 0 ? false : true} isClearable={true} value={otherSaleStoreList.filter(function (option) { return option.saleStoreId === otherSelOptions @@ -1715,11 +1727,29 @@ export default function StuffDetail() {
- - + { + handleRadioChange(e) + }} + /> +
- + { + handleRadioChange(e) + }} + />
@@ -2211,11 +2241,29 @@ export default function StuffDetail() {
- - + { + handleRadioChange(e) + }} + /> +
- + { + handleRadioChange(e) + }} + />
diff --git a/src/components/management/StuffSearchCondition.jsx b/src/components/management/StuffSearchCondition.jsx index 7bd8f456..59a4d23c 100644 --- a/src/components/management/StuffSearchCondition.jsx +++ b/src/components/management/StuffSearchCondition.jsx @@ -184,34 +184,36 @@ export default function StuffSearchCondition() { setSchSelSaleStoreList(allList) setFavoriteStoreList(favList) setShowSaleStoreList(favList) - setSchSelSaleStoreId(session?.storeId) + // setSchSelSaleStoreId(session?.storeId) setStuffSearch({ ...stuffSearch, code: 'S', - schSelSaleStoreId: session?.storeId, + // schSelSaleStoreId: session?.storeId, }) //T01일때 2차 판매점 호출하기 디폴트로 1차점을 본인으로 셋팅해서 세션storeId사용 - url = `/api/object/saleStore/${session?.storeId}/list?firstFlg=0&userId=${session?.userId}` + // 디폴트 셋팅 안하기로 + // url = `/api/object/saleStore/${session?.storeId}/list?firstFlg=0&userId=${session?.userId}` - get({ url: url }).then((res) => { - if (!isEmptyArray(res)) { - res.map((row) => { - row.value = row.saleStoreId - row.label = row.saleStoreName - }) + // get({ url: url }).then((res) => { + // if (!isEmptyArray(res)) { + // res.map((row) => { + // row.value = row.saleStoreId + // row.label = row.saleStoreName + // }) - otherList = res - setOtherSaleStoreList(otherList) - } else { - setOtherSaleStoreList([]) - } - }) + // otherList = res + // setOtherSaleStoreList(otherList) + // } else { + // setOtherSaleStoreList([]) + // } + // }) } else { if (session?.storeLvl === '1') { allList = res favList = res.filter((row) => row.priority !== 'B') otherList = res.filter((row) => row.firstAgentYn === 'N') + setSchSelSaleStoreList(allList) setFavoriteStoreList(allList) setShowSaleStoreList(allList) @@ -584,7 +586,7 @@ export default function StuffSearchCondition() { onChange={onSelectionChange2} getOptionLabel={(x) => x.saleStoreName} getOptionValue={(x) => x.saleStoreId} - isDisabled={otherSaleStoreList.length > 1 ? false : true} + isDisabled={otherSaleStoreList.length > 0 ? false : true} isClearable={true} value={otherSaleStoreList.filter(function (option) { return option.saleStoreId === otherSaleStoreId From 691b5a092937ee4105416beed843d805d4ef2519 Mon Sep 17 00:00:00 2001 From: minsik Date: Fri, 8 Nov 2024 14:51:59 +0900 Subject: [PATCH 38/51] =?UTF-8?q?=EC=8B=A4=EC=B8=A1=EC=B9=98=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20modal=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../roofAllocation/ActualSizeSetting.jsx | 122 ++++++++++++++++++ .../roofcover/useRoofAllocationSetting.js | 121 +++++++++++++++-- src/locales/ja.json | 6 + src/locales/ko.json | 6 + 4 files changed, 244 insertions(+), 11 deletions(-) create mode 100644 src/components/floor-plan/modal/roofAllocation/ActualSizeSetting.jsx diff --git a/src/components/floor-plan/modal/roofAllocation/ActualSizeSetting.jsx b/src/components/floor-plan/modal/roofAllocation/ActualSizeSetting.jsx new file mode 100644 index 00000000..edca1208 --- /dev/null +++ b/src/components/floor-plan/modal/roofAllocation/ActualSizeSetting.jsx @@ -0,0 +1,122 @@ +import WithDraggable from '@/components/common/draggable/WithDraggable' +import { useMessage } from '@/hooks/useMessage' +import { usePopup } from '@/hooks/usePopup' +import { useRecoilValue } from 'recoil' +import { contextPopupPositionState } from '@/store/popupAtom' +import { useEffect, useState } from 'react' +import { currentObjectState } from '@/store/canvasAtom' +import { useRoofAllocationSetting } from '@/hooks/roofcover/useRoofAllocationSetting' +import { useSwal } from '@/hooks/useSwal' + +export default function ActualSizeSetting(props) { + const contextPopupPosition = useRecoilValue(contextPopupPositionState) + const { id, pos = contextPopupPosition } = props + const currentObject = useRecoilValue(currentObjectState) + const [planeSize, setPlaneSize] = useState(0) + const [actualSize, setActualSize] = useState(0) + const { setLineSize, handleAlloc } = useRoofAllocationSetting() + const { closePopup } = usePopup() + const { getMessage } = useMessage() + const { swalFire } = useSwal() + useEffect(() => { + if (currentObject && currentObject.attributes) { + setPlaneSize(currentObject.attributes.planeSize ?? 0) + setActualSize(currentObject.attributes.actualSize ?? 0) + } + }, [currentObject]) + + const handleFinish = () => { + swalFire({ + text: '완료 하시겠습니까?', + type: 'confirm', + confirmFn: () => { + handleAlloc() + }, + }) + } + + const handleClose = () => { + swalFire({ + text: '완료 하시겠습니까?', + type: 'confirm', + confirmFn: () => { + handleAlloc() + }, + // denyFn: () => { + // swalFire({ text: '취소되었습니다.', icon: 'error' }) + // }, + }) + } + + const handleApply = () => { + if (!currentObject) { + swalFire({ type: 'alert', icon: 'error', text: getMessage('modal.actual.size.setting.not.exist.auxiliary.line') }) + return + } + if (actualSize !== 0) { + setLineSize(currentObject?.id, actualSize) + } else { + swalFire({ type: 'alert', icon: 'error', text: getMessage('modal.actual.size.setting.not.exist.size') }) + } + } + + return ( + +
+
+

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

+ +
+
+
+ {getMessage('modal.actual.size.setting.info')} +
+
+
{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 +
+
+
+
+
+
+
+ + +
+
+
+
+ ) +} diff --git a/src/hooks/roofcover/useRoofAllocationSetting.js b/src/hooks/roofcover/useRoofAllocationSetting.js index 921e737a..2d57e9b5 100644 --- a/src/hooks/roofcover/useRoofAllocationSetting.js +++ b/src/hooks/roofcover/useRoofAllocationSetting.js @@ -1,5 +1,5 @@ import { useRecoilValue } from 'recoil' -import { canvasState } from '@/store/canvasAtom' +import { canvasState, currentObjectState } from '@/store/canvasAtom' import { useEffect, useState } from 'react' import { setSurfaceShapePattern } from '@/util/canvas-util' import { useSwal } from '@/hooks/useSwal' @@ -7,16 +7,20 @@ import { usePolygon } from '@/hooks/usePolygon' import { roofDisplaySelector } from '@/store/settingAtom' import { usePopup } from '@/hooks/usePopup' import { POLYGON_TYPE } from '@/common/common' +import { v4 as uuidv4 } from 'uuid' +import ActualSizeSetting from '@/components/floor-plan/modal/roofAllocation/ActualSizeSetting' +import { useMessage } from '@/hooks/useMessage' // 지붕면 할당 export function useRoofAllocationSetting(id) { const canvas = useRecoilValue(canvasState) const roofDisplay = useRecoilValue(roofDisplaySelector) const { drawDirectionArrow, addLengthText, splitPolygonWithLines } = usePolygon() - const { closePopup } = usePopup() - + const [popupId, setPopupId] = useState(uuidv4()) + const { addPopup, closePopup, closeAll } = usePopup() + const { getMessage } = useMessage() + const currentObject = useRecoilValue(currentObjectState) const { swalFire } = useSwal() - const roofMaterials = [ { id: 'A', @@ -77,23 +81,55 @@ export function useRoofAllocationSetting(id) { ]) const [radioValue, setRadioValue] = useState('A') + const [editingLines, setEditingLines] = useState([]) const [selectedRoofMaterial, setSelectedRoofMaterial] = useState(roofMaterials[0]) + useEffect(() => { + const roofBases = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF) // roofPolygon.innerLines + + roofBases.forEach((roof) => { + roof.innerLines.forEach((line) => { + if (!line.attributes.actualSize || line.attributes?.actualSize === 0) { + line.set({ + strokeWidth: 4, + stroke: 'black', + selectable: true, + }) + } + + if (editingLines.includes(line)) { + line.set({ + strokeWidth: 2, + stroke: 'black', + selectable: true, + }) + } + }) + }) + if (currentObject) { + console.log(currentObject.name) + if (currentObject.name.toLowerCase().includes('line')) { + currentObject.set({ + strokeWidth: 4, + stroke: '#EA10AC', + }) + } + } + }, [currentObject]) + useEffect(() => { const roofBases = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF) if (roofBases.length === 0) { swalFire({ text: '할당할 지붕이 없습니다.' }) closePopup(id) } - // if (type === POLYGON_TYPE.ROOF) { - // // 지붕면 할당 - // - // } else if ('roof') { - // // 지붕재 변경 - // } }, []) + useEffect(() => { + console.log('editingLines', editingLines) + }, [editingLines]) + const onAddRoofMaterial = () => { setValues([...values, selectedRoofMaterial]) } @@ -104,6 +140,49 @@ export function useRoofAllocationSetting(id) { // 선택한 지붕재로 할당 const handleSave = () => { + // 모두 actualSize 있으면 바로 적용 없으면 actualSize 설정 + if (checkInnerLines()) { + addPopup(popupId, 1, ) + } else { + apply() + } + } + + const handleAlloc = () => { + if (!checkInnerLines()) { + apply() + closePopup(popupId) + } else { + swalFire({ + type: 'alert', + icon: 'error', + text: getMessage('실제치수를 입력해 주세요.'), + }) + } + } + + const checkInnerLines = () => { + const roofBases = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF) // roofPolygon.innerLines + let result = false + console.log(roofBases) + roofBases.forEach((roof) => { + roof.innerLines.forEach((line) => { + if (!line.attributes.actualSize || line.attributes?.actualSize === 0) { + line.set({ + strokeWidth: 4, + stroke: 'black', + selectable: true, + }) + result = true + } + }) + }) + if (result) canvas?.renderAll() + + return result + } + + const apply = () => { const roofBases = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF) const wallLines = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.WALL) roofBases.forEach((roofBase) => { @@ -135,8 +214,26 @@ export function useRoofAllocationSetting(id) { removeTargets.forEach((obj) => { canvas.remove(obj) }) + setEditingLines([]) + closeAll() + } - closePopup(id) + const setLineSize = (id, size) => { + const roofBases = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF) + roofBases.forEach((roof) => { + roof.innerLines.forEach((line) => { + if (id === line.id) { + setEditingLines([...editingLines.filter((editLine) => editLine.id !== line.id), line]) + line.attributes.actualSize = size + line.set({ + strokeWidth: 2, + stroke: 'black', + }) + } + }) + }) + + canvas?.renderAll() } const handleRadioOnChange = (e) => { @@ -148,6 +245,8 @@ export function useRoofAllocationSetting(id) { onAddRoofMaterial, onDeleteRoofMaterial, handleRadioOnChange, + handleAlloc, + setLineSize, widths, lengths, rafters, diff --git a/src/locales/ja.json b/src/locales/ja.json index 05ab09cf..63855bc6 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -285,6 +285,12 @@ "modal.flow.direction.setting": "流れ方向の設定", "modal.flow.direction.setting.info": "流れ方向を選択してください。", "modal.image.size.setting": "画像のサイズ変更", + "modal.actual.size.setting": "実測値設定", + "modal.actual.size.setting.info": "※隅棟・谷・棟の実際の寸法を入力してください。", + "modal.actual.size.setting.not.exist.auxiliary.line": "실측치 입력할 보조선을 선택해 주세요(JA)", + "modal.actual.size.setting.not.exist.size": "실제치수 길이를 입력해 주세요.(JA)", + "modal.actual.size.setting.plane.size.length": "廊下の寸法の長さ", + "modal.actual.size.setting.actual.size.length": "実寸長", "plan.message.confirm.save": "PLAN을 저장하시겠습니까?", "plan.message.confirm.copy": "PLAN을 복사하시겠습니까?", "plan.message.confirm.delete": "PLAN을 삭제하시겠습니까?", diff --git a/src/locales/ko.json b/src/locales/ko.json index d8cef240..4f9ab2ae 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -290,6 +290,12 @@ "modal.flow.direction.setting": "흐름 방향 설정", "modal.flow.direction.setting.info": "흐름방향을 선택하세요.", "modal.image.size.setting": "이미지 크기 조절", + "modal.actual.size.setting": "실측치 설정", + "modal.actual.size.setting.info": "※隅棟・谷・棟의 실제 치수를 입력해주세요.", + "modal.actual.size.setting.not.exist.auxiliary.line": "실측치 입력할 보조선을 선택해 주세요", + "modal.actual.size.setting.not.exist.size": "실제치수 길이를 입력해 주세요", + "modal.actual.size.setting.plane.size.length": "복도치수 길이", + "modal.actual.size.setting.actual.size.length": "실제치수 길이", "plan.message.confirm.save": "PLAN을 저장하시겠습니까?", "plan.message.confirm.copy": "PLAN을 복사하시겠습니까?", "plan.message.confirm.delete": "PLAN을 삭제하시겠습니까?", From b4504c5b78a8d2b478bdce04668ca576972dfe53 Mon Sep 17 00:00:00 2001 From: Jaeyoung Lee Date: Fri, 8 Nov 2024 14:59:43 +0900 Subject: [PATCH 39/51] =?UTF-8?q?=EB=A7=88=EB=A3=A8=20=EC=A7=80=EB=B6=95?= =?UTF-8?q?=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Roof2.jsx | 11 ++++++++++- src/util/qpolygon-utils.js | 10 ++-------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/components/Roof2.jsx b/src/components/Roof2.jsx index 82ba40c1..081eedc2 100644 --- a/src/components/Roof2.jsx +++ b/src/components/Roof2.jsx @@ -431,7 +431,16 @@ export default function Roof2(props) { { x: 450, y: 850 }, ] - const polygon = new QPolygon(type2, { + 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 polygon = new QPolygon(test1, { fill: 'transparent', stroke: 'green', strokeWidth: 1, diff --git a/src/util/qpolygon-utils.js b/src/util/qpolygon-utils.js index 69102461..679562ec 100644 --- a/src/util/qpolygon-utils.js +++ b/src/util/qpolygon-utils.js @@ -1334,10 +1334,9 @@ const drawRidge = (roof, canvas) => { let xEqualInnerLines = anotherRoof.filter((roof) => roof.x1 === roof.x2 && isInnerLine(prevRoof, currentRoof, nextRoof, roof)), //x가 같은 내부선 yEqualInnerLines = anotherRoof.filter((roof) => roof.y1 === roof.y2 && isInnerLine(prevRoof, currentRoof, nextRoof, roof)) //y가 같은 내부선 - console.log('xEqualInnerLines', xEqualInnerLines, 'yEqualInnerLines', yEqualInnerLines) let ridgeBaseLength = Math.round(currentRoof.attributes.planeSize / 2), // 지붕의 기반 길이 ridgeMaxLength = Math.min(prevRoof.attributes.planeSize, nextRoof.attributes.planeSize), // 지붕의 최대 길이. 이전, 다음 벽 중 짧은 길이 - ridgeAcrossLength = Math.abs(ridgeMaxLength - currentRoof.attributes.planeSize) // 맞은편 벽까지의 길이 - 지붕의 기반 길이 + ridgeAcrossLength = Math.abs(Math.max(prevRoof.attributes.planeSize, nextRoof.attributes.planeSize) - currentRoof.attributes.planeSize) // 맞은편 벽까지의 길이 - 지붕의 기반 길이 let acrossRoof = anotherRoof .filter((roof) => { @@ -1348,8 +1347,6 @@ const drawRidge = (roof, canvas) => { } }) .reduce((prev, current) => { - console.log('prev', prev, 'current', current) - console.log('currentRoof', currentRoof) let hasBetweenRoof = false if (current.x1 === current.x2) { hasBetweenRoof = roofLines @@ -1379,19 +1376,15 @@ const drawRidge = (roof, canvas) => { currentX2 = Math.abs(currentRoof.x1 - currentX2) < Math.abs(currentRoof.x1 - line.x1) ? currentX2 : line.x1 }) } - console.log('line :', line) const isX1Between = (line.x1 > currentRoof.x1 && line.x1 < currentX2) || (line.x1 > currentX2 && line.x1 < currentRoof.x1) const isX2Between = (line.x2 > currentRoof.x1 && line.x2 < currentX2) || (line.x2 > currentX2 && line.x2 < currentRoof.x1) const isY1Between = (line.y1 > currentRoof.y1 && line.y1 < current.y1) || (line.y1 > currentRoof.y1 && line.y1 < current.y1) const isY2Between = (line.y2 > currentRoof.y1 && line.y2 < current.y1) || (line.y2 > currentRoof.y1 && line.y2 < current.y1) - console.log('isX1Between', isX1Between, 'isX2Between', isX2Between, 'isY1Between', isY1Between, 'isY2Between', isY2Between) return isX1Between && isX2Between && isY1Between && isY2Between }) } - console.log('hasBetweenRoof', hasBetweenRoof) - if (prev !== undefined) { if (currentRoof.x1 === currentRoof.x2) { return Math.abs(currentRoof.y1 - prev.y1) > Math.abs(currentRoof.y1 - current.y1) ? prev : current @@ -1429,6 +1422,7 @@ const drawRidge = (roof, canvas) => { ridgeBaseLength = ridgeBaseLength / 10 ridgeMaxLength = ridgeMaxLength / 10 ridgeAcrossLength = ridgeAcrossLength / 10 + if (ridgeBaseLength > 0 && ridgeMaxLength > 0 && ridgeAcrossLength > 0) { let ridgeLength = Math.min(ridgeMaxLength, ridgeAcrossLength) if (currentRoof.x1 === currentRoof.x2) { From 845ff99f077d3b0c23ed349b81e429f3076be8c7 Mon Sep 17 00:00:00 2001 From: minsik Date: Fri, 8 Nov 2024 15:31:37 +0900 Subject: [PATCH 40/51] =?UTF-8?q?=EC=8B=A4=EC=B8=A1=EC=B9=98=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20modal=20close=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/roofcover/useRoofAllocationSetting.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/hooks/roofcover/useRoofAllocationSetting.js b/src/hooks/roofcover/useRoofAllocationSetting.js index 2d57e9b5..b99af935 100644 --- a/src/hooks/roofcover/useRoofAllocationSetting.js +++ b/src/hooks/roofcover/useRoofAllocationSetting.js @@ -151,7 +151,6 @@ export function useRoofAllocationSetting(id) { const handleAlloc = () => { if (!checkInnerLines()) { apply() - closePopup(popupId) } else { swalFire({ type: 'alert', From 56e8337c54d17a2f67cc5314b9bad3d6b6058bcb Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Fri, 8 Nov 2024 15:36:33 +0900 Subject: [PATCH 41/51] default planeSize --- src/hooks/usePolygon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hooks/usePolygon.js b/src/hooks/usePolygon.js index 699b4f09..9b3a8e98 100644 --- a/src/hooks/usePolygon.js +++ b/src/hooks/usePolygon.js @@ -75,7 +75,7 @@ export const usePolygon = () => { const maxY = line.top + line.length const degree = (Math.atan2(y2 - y1, x2 - x1) * 180) / Math.PI - const text = new fabric.Textbox(actualSize ? actualSize.toString() : planeSize ? planeSize.toString() : length.toString(), { + const text = new fabric.Textbox(planeSize ? planeSize.toString() : length.toString(), { left: left, top: top, fontSize: lengthTextFontOptions.fontSize.value, From 73829ff5dd66284f91f4e490977c7e8c09bb7313 Mon Sep 17 00:00:00 2001 From: Jaeyoung Lee Date: Fri, 8 Nov 2024 16:27:06 +0900 Subject: [PATCH 42/51] =?UTF-8?q?=EB=A7=88=EB=A3=A8=20=EC=A7=80=EB=B6=95?= =?UTF-8?q?=20=EC=B2=98=EB=A7=88=20=EA=B8=B8=EC=9D=B4=20=EC=98=A4=EB=A5=98?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Roof2.jsx | 11 ++++++++++- src/util/qpolygon-utils.js | 5 ++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/components/Roof2.jsx b/src/components/Roof2.jsx index 081eedc2..021357c4 100644 --- a/src/components/Roof2.jsx +++ b/src/components/Roof2.jsx @@ -440,7 +440,16 @@ export default function Roof2(props) { { x: 1457, y: 178 }, ] - const polygon = new QPolygon(test1, { + const test2 = [ + { x: 113, y: 114.9 }, + { x: 113, y: 371.9 }, + { x: 762, y: 371.9 }, + { x: 762, y: 818.7 }, + { x: 1468.6, y: 818.7 }, + { x: 1468.6, y: 114.9 }, + ] + + const polygon = new QPolygon(type2, { fill: 'transparent', stroke: 'green', strokeWidth: 1, diff --git a/src/util/qpolygon-utils.js b/src/util/qpolygon-utils.js index 679562ec..ed375ec5 100644 --- a/src/util/qpolygon-utils.js +++ b/src/util/qpolygon-utils.js @@ -1338,6 +1338,7 @@ const drawRidge = (roof, canvas) => { ridgeMaxLength = Math.min(prevRoof.attributes.planeSize, nextRoof.attributes.planeSize), // 지붕의 최대 길이. 이전, 다음 벽 중 짧은 길이 ridgeAcrossLength = Math.abs(Math.max(prevRoof.attributes.planeSize, nextRoof.attributes.planeSize) - currentRoof.attributes.planeSize) // 맞은편 벽까지의 길이 - 지붕의 기반 길이 + console.log('ridgeBaseLength', ridgeBaseLength, 'ridgeMaxLength', ridgeMaxLength, 'ridgeAcrossLength', ridgeAcrossLength) let acrossRoof = anotherRoof .filter((roof) => { const angle1 = calculateAngle(currentRoof.startPoint, currentRoof.endPoint) @@ -1423,6 +1424,8 @@ const drawRidge = (roof, canvas) => { ridgeMaxLength = ridgeMaxLength / 10 ridgeAcrossLength = ridgeAcrossLength / 10 + console.log('ridgeBaseLength', ridgeBaseLength, 'ridgeMaxLength', ridgeMaxLength, 'ridgeAcrossLength', ridgeAcrossLength) + if (ridgeBaseLength > 0 && ridgeMaxLength > 0 && ridgeAcrossLength > 0) { let ridgeLength = Math.min(ridgeMaxLength, ridgeAcrossLength) if (currentRoof.x1 === currentRoof.x2) { @@ -1776,7 +1779,7 @@ const drawHips = (roof, canvas) => { }) canvas.add(hip) const hipBase = ((Math.abs(hip.x1 - hip.x2) + Math.abs(hip.y1 - hip.y2)) / 2) * 10 - const hipHeight = Math.round(hipBase / Math.tan(((90 - currentRoof.attributes.degree) * Math.PI) / 180)) + const hipHeight = Math.round(hipBase / Math.tan(((90 - currentDegree) * Math.PI) / 180)) hip.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip.x1 - hip.x2, 2) + Math.pow(hip.y1 - hip.y2, 2))) * 10 if (prevDegree === currentDegree) { hip.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip.attributes.planeSize, 2) + Math.pow(hipHeight, 2))) From 21d758834d7fb0ccd20f2092e725da81e58f7664 Mon Sep 17 00:00:00 2001 From: basssy Date: Sat, 9 Nov 2024 02:05:26 +0900 Subject: [PATCH 43/51] =?UTF-8?q?=EA=B2=AC=EC=A0=81=EC=84=9C=20=EC=83=81?= =?UTF-8?q?=EC=84=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/estimate/Estimate.jsx | 149 +++++++++++++++--- .../estimate/useEstimateController.js | 74 ++++----- src/locales/ja.json | 14 +- src/locales/ko.json | 14 +- 4 files changed, 169 insertions(+), 82 deletions(-) diff --git a/src/components/estimate/Estimate.jsx b/src/components/estimate/Estimate.jsx index 442c597b..4d816f4b 100644 --- a/src/components/estimate/Estimate.jsx +++ b/src/components/estimate/Estimate.jsx @@ -15,7 +15,7 @@ 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 EstimateItemTable from './EstimateItemTable' +import { convertNumberToPriceDecimal } from '@/util/common-utils' export default function Estimate({ params }) { const { session } = useContext(SessionContext) @@ -36,6 +36,8 @@ export default function Estimate({ params }) { const [storePriceList, setStorePriceList] = useState([]) //가격표시 option + const [tempPriceCd, setTempPriceCd] = useState('') + const [startDate, setStartDate] = useState(new Date()) const singleDatePickerProps = { startDate, @@ -47,7 +49,7 @@ export default function Estimate({ params }) { //견적서 상세데이터 const { state, setState } = useEstimateController(params.pid) - const [itemList, setItemList] = useState([]) + const [itemList, setItemList] = useState([]) //기존 아이템 리스트 //견적특이사항 List const [specialNoteList, setSpecialNoteList] = useState([]) @@ -151,9 +153,13 @@ export default function Estimate({ params }) { objectNo: objectNo, no: no, } + await promisePost({ url: 'api/file/fileDelete', data: delParams }).then((res) => { if (res.status === 204) { setOriginFiles(originFiles.filter((file) => file.objectNo === objectNo && file.no !== no)) + setState({ + fileList: originFiles.filter((file) => file.objectNo === objectNo && file.no !== no), + }) } }) } @@ -165,13 +171,14 @@ export default function Estimate({ params }) { } }, [state?.itemList]) - //가격표시 option 세팅 + //가격표시 option 최초세팅 useEffect(() => { const param = { saleStoreId: session.storeId, sapSalesStoreCd: session.custCd, docTpCd: state?.estimateType, } + const apiUrl = `/api/estimate/price/store-price-list?${queryStringFormatter(param)}` get({ url: apiUrl }).then((res) => { if (isNotEmptyArray(res?.data)) { @@ -180,21 +187,58 @@ export default function Estimate({ params }) { }) }, [state?.estimateType]) + useEffect(() => { + if (state.priceCd) { + setTempPriceCd(state.priceCd) + } + }, [state?.priceCd]) + + //가격표시 option 변경시 + useEffect(() => { + if (tempPriceCd !== '') { + const param = { + saleStoreId: session.storeId, + sapSalesStoreCd: session.custCd, + docTpCd: tempPriceCd, + } + + const apiUrl = `/api/estimate/price/store-price-list?${queryStringFormatter(param)}` + get({ url: apiUrl }).then((res) => { + if (isNotEmptyArray(res?.data)) { + setStorePriceList(res.data) + } + }) + } + }, [tempPriceCd]) + //Pricing 버튼 const handlePricing = async (priceCd) => { const param = { saleStoreId: session.storeId, sapSalesStoreCd: session.custCd, docTpCd: state.estimateType, - priceCd: priceCd, - itemIdList: [], //아이템 + priceCd: session.storeLvl === '1' ? tempPriceCd : priceCd, + itemIdList: state.itemList, //아이템 최초정보로 호출 } - console.log('param::', param) - return + // console.log('프라이싱파람::', param) await promisePost({ url: '/api/estimate/price/item-price-list', data: param }).then((res) => { - console.log('프라이싱결과::::::', res) - //아이템쪽 다 새로고침............SUCK!!! + if (res) { + if (res.status === 200) { + const data = res.data + if (data.result.code === 200) { + if (isNotEmptyArray(data.data2)) { + //아이템쪽 다 새로고침............ + //성공후.. + //기존itemList랑 프라이싱결과랑 비교해서 단가만 업뎃 서로 갯수가 안맞을 수 있음 없는 itemId면 unitPrice 0으로 + //itemId로 비교해서 단가정보만 업데이트 + setState({ + priceCd: session.storeLvl === '1' ? tempPriceCd : priceCd, + }) + } + } + } + } }) } @@ -249,7 +293,7 @@ export default function Estimate({ params }) { {/* 1차 판매점명 */} {getMessage('estimate.detail.saleStoreId')} - + {state?.firstSaleStoreName} {/* 견적일 */} {getMessage('estimate.detail.estimateDate')} * @@ -263,7 +307,7 @@ export default function Estimate({ params }) { {/* 2차 판매점명 */} {getMessage('estimate.detail.otherSaleStoreId')} - + {state?.agencySaleStoreName} {/* 담당자 */} {getMessage('estimate.detail.receiveUser')} * @@ -622,7 +666,7 @@ export default function Estimate({ params }) { + +
+ + {item?.dispOrder * 100} + +
+
+ +
+ + {item.unit} + +
+
+ +
+ {/*
+ OPEN아이콘 처리 +
*/} +
+ + {convertNumberToPriceDecimal(item?.saleTotPrice)} + + ) + })} + {/*
@@ -716,7 +819,7 @@ export default function Estimate({ params }) { 100
-
{/* { - setSpecialNoteList((specialNote) => - specialNote.map((temp) => (temp.code === row.code ? { ...temp, text: !temp.text } : temp)), - ) - settingShowContent(row.code, event) - }} - /> - + {specialNoteList.length > 0 && + specialNoteList.map((row) => { + return ( +
{ + settingShowContent(row.code, event) + }} + > +
+ { + setSpecialNoteList((specialNote) => + specialNote.map((temp) => (temp.code === row.code ? { ...temp, text: !temp.text } : temp)), + ) + settingShowContent(row.code, event) + }} + /> + +
-
- ) - })} + ) + })}
{/* 견적특이사항 선택한 내용 영역시작 */}
@@ -706,13 +717,13 @@ export default function Estimate({ params }) {
-
@@ -763,7 +774,21 @@ export default function Estimate({ params }) {
- x.saleStoreName} + // getOptionValue={(x) => x.saleStoreId} + isClearable={true} + isDisabled={false} + // value={saleStoreList.filter(function (option) { + // return option.saleStoreId === selOptions + // })} + />
{item?.itemChangeFlg === '1' && (
@@ -782,7 +807,8 @@ export default function Estimate({ params }) { type="button" className="grid-tip" onClick={() => { - console.log('제품특이사항 모달팝업:::::::::', item?.specialNoteCd) + setProductFeaturesPopupOpen(true) + setShowProductFeatureData(item?.specialNoteCd) }} > )} @@ -809,49 +835,6 @@ export default function Estimate({ params }) { ) })} - {/* - -
- - -
- - 100 - -
-
-
- -
-
- - -
-
HNW-MC4-CHN30
-
- - -
-
- - -
- -
- - セット - -
-
- -
-
- -
-
- - 5,561,000 - */}
@@ -861,6 +844,13 @@ export default function Estimate({ params }) {
{/* 기본정보끝 */}
+ {productFeaturesPopupOpen && ( + + )}
) } diff --git a/src/components/estimate/popup/ProductFeaturesPop.jsx b/src/components/estimate/popup/ProductFeaturesPop.jsx new file mode 100644 index 00000000..428c6a8e --- /dev/null +++ b/src/components/estimate/popup/ProductFeaturesPop.jsx @@ -0,0 +1,51 @@ +'use client' +import { useState } from 'react' +import { useMessage } from '@/hooks/useMessage' +export default function ProductFeaturesPop({ specialNoteList, showProductFeatureData, setProductFeaturesPopupOpen }) { + console.log('위에서 넘어온거::', specialNoteList) + console.log('위에서 넘어온거::', showProductFeatureData) + //split('、') + + const { getMessage } = useMessage() + return ( +
+
+
+
+

{getMessage('estimate.detail.productFeaturesPopup.title')}

+ +
+
+
+
+
+
제목
+
내용
+
+
+
+
+ +
+
+
+
+
+ ) +} diff --git a/src/hooks/floorPlan/estimate/useEstimateController.js b/src/hooks/floorPlan/estimate/useEstimateController.js index df3e4450..05d10554 100644 --- a/src/hooks/floorPlan/estimate/useEstimateController.js +++ b/src/hooks/floorPlan/estimate/useEstimateController.js @@ -76,27 +76,20 @@ export const useEstimateController = (planNo) => { } const addItem = () => { - const newItemId = Math.max(...state.itemList.map((item) => item.itemId)) + 1 + const newItemDispOrder = (Math.max(...state.itemList.map((item) => item.dispOrder)) + 1) * 100 setState({ itemList: [ ...state.itemList, { - dispOrder: '1', - itemId: newItemId, - amount: '', - fileUploadFlg: '0', - itemChangeFlg: '0', - pkgMaterialFlg: '0', - specialNoteCd: '', - itemGroup: '', + dispOrder: newItemDispOrder, + itemId: '', //제품번호 + itemNo: '', //형명 itemName: '', - itemNo: '', - moduleFlg: '', - pnowW: '', - salePrice: '', - saleTotPrice: '', - specification: '', - unit: '', + amount: '', //수량 + unitPrice: '0', + unit: '', //단위 + salePrice: '0', //단가 + saleTotPrice: '0', //금액(부가세별도) }, ], }) diff --git a/src/locales/ja.json b/src/locales/ja.json index 3e79412e..ec6a7b69 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -847,8 +847,8 @@ "estimate.detail.showPrice.description2": "追加, 変更資材", "estimate.detail.showPrice.description3": "添付必須", "estimate.detail.showPrice.description4": "クリックして製品の特異性を確認する", - "estimate.detail.showPrice.btn2": "製品を追加", - "estimate.detail.showPrice.btn3": "製品削除", + "estimate.detail.showPrice.addItem": "製品を追加", + "estimate.detail.showPrice.delItem": "製品削除", "estimate.detail.itemTableHeader.dispOrder": "アイテム", "estimate.detail.itemTableHeader.itemId": "品番", "estimate.detail.itemTableHeader.itemNo": "型板", @@ -874,6 +874,8 @@ "estimate.detail.docPopup.schDrawingFlg.schDrawingFlg1": "含まない", "estimate.detail.docPopup.close": "閉じる", "estimate.detail.docPopup.docDownload": "文書のダウンロード", + "estimate.detail.productFeaturesPopup.title": "製品特異事項", + "estimate.detail.productFeaturesPopup.close": "閉じる", "estimate.detail.save.alertMsg": "保存されている見積書で製品を変更した場合、図面や回路には反映されません.", "estimate.detail.save.requiredMsg": "ファイル添付が必須のアイテムがあります。ファイルを添付するか、後日添付をチェックしてください.", "estimate.detail.reset.confirmMsg": "保存した見積書情報が初期化され、図面情報が反映されます。本当に初期化しますか?", diff --git a/src/locales/ko.json b/src/locales/ko.json index a2ef69b3..c8bde290 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -853,8 +853,8 @@ "estimate.detail.showPrice.description2": "추가, 변경 자재", "estimate.detail.showPrice.description3": "첨부필수", "estimate.detail.showPrice.description4": "클릭하여 제품 특이사항 확인", - "estimate.detail.showPrice.btn2": "제품추가", - "estimate.detail.showPrice.btn3": "제품삭제", + "estimate.detail.showPrice.addItem": "제품추가", + "estimate.detail.showPrice.delItem": "제품삭제", "estimate.detail.itemTableHeader.dispOrder": "Item", "estimate.detail.itemTableHeader.itemId": "품번", "estimate.detail.itemTableHeader.itemNo": "형명", @@ -880,6 +880,8 @@ "estimate.detail.docPopup.schDrawingFlg.schDrawingFlg1": "미포함", "estimate.detail.docPopup.close": "닫기", "estimate.detail.docPopup.docDownload": "문서 다운로드", + "estimate.detail.productFeaturesPopup.title": "제품특이사항", + "estimate.detail.productFeaturesPopup.close": "닫기", "estimate.detail.save.alertMsg": "저장되었습니다. 견적서에서 제품을 변경할 경우, 도면 및 회로에 반영되지 않습니다.", "estimate.detail.save.requiredMsg": "파일첨부가 필수인 아이템이 있습니다. 파일을 첨부하거나 후일첨부를 체크해주십시오.", "estimate.detail.reset.confirmMsg": "저장된 견적서 정보가 초기화되고, 도면정보가 반영됩니다. 정말로 초기화 하시겠습니까?", From 86d9e574bb4e699c0483005288c0b2e78744ad34 Mon Sep 17 00:00:00 2001 From: yjnoh Date: Mon, 11 Nov 2024 10:19:40 +0900 Subject: [PATCH 46/51] =?UTF-8?q?=EC=84=A0=EC=86=8D=EC=84=B1=20=EC=9E=91?= =?UTF-8?q?=EC=97=85=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/common/common.js | 1 + .../flowDirection/FlowDirectionSetting.jsx | 26 +-- .../lineProperty/LinePropertySetting.jsx | 21 ++- src/hooks/surface/useSurfaceShapeBatch.js | 178 ++++++++++++++++-- src/hooks/useContextMenu.js | 9 +- src/locales/ko.json | 4 + 6 files changed, 210 insertions(+), 29 deletions(-) diff --git a/src/common/common.js b/src/common/common.js index d0016af1..eb86bb89 100644 --- a/src/common/common.js +++ b/src/common/common.js @@ -161,6 +161,7 @@ export const SAVE_KEY = [ 'groupId', 'planeSize', 'actualSize', + 'surfaceId', ] export const OBJECT_PROTOTYPE = [fabric.Line.prototype, fabric.Polygon.prototype, fabric.Triangle.prototype] diff --git a/src/components/floor-plan/modal/flowDirection/FlowDirectionSetting.jsx b/src/components/floor-plan/modal/flowDirection/FlowDirectionSetting.jsx index 8e54c646..effb4717 100644 --- a/src/components/floor-plan/modal/flowDirection/FlowDirectionSetting.jsx +++ b/src/components/floor-plan/modal/flowDirection/FlowDirectionSetting.jsx @@ -5,14 +5,18 @@ import { useRecoilValue } from 'recoil' import { contextPopupPositionState } from '@/store/popupAtom' import { useMessage } from '@/hooks/useMessage' import { usePopup } from '@/hooks/usePopup' - +import { useSurfaceShapeBatch } from '@/hooks/surface/useSurfaceShapeBatch' export default function FlowDirectionSetting(props) { const contextPopupPosition = useRecoilValue(contextPopupPositionState) const { id, pos = contextPopupPosition, target } = props const { getMessage } = useMessage() const { closePopup } = usePopup() const [compasDeg, setCompasDeg] = useState(360) + const [flowDirection, setFlowDirection] = useState(target.direction) + const { changeSurfaceFlowDirection } = useSurfaceShapeBatch() + const orientations = [ + // { name: `${getMessage('commons.none')}`, value: 0 }, { name: `${getMessage('commons.south')}`, value: 360 }, { name: `${getMessage('commons.south')}${getMessage('commons.east')}`, value: 315 }, { name: `${getMessage('commons.south')}${getMessage('commons.west')}`, value: 45 }, @@ -75,13 +79,13 @@ export default function FlowDirectionSetting(props) {
{getMessage('commons.north')} - + {getMessage('commons.east')} - + {getMessage('commons.south')} - + {getMessage('commons.west')} - +
@@ -111,18 +115,14 @@ export default function FlowDirectionSetting(props) { key={index} className={`circle ${compasDeg === 15 * (12 + index) ? 'act' : ''}`} onClick={() => setCompasDeg(15 * (12 + index))} - > - {13 - index} -
+ >
))} {Array.from({ length: 180 / 15 - 1 }).map((dot, index) => (
setCompasDeg(15 * (index + 1))} - > - {24 - index} -
+ >
))}
@@ -133,7 +133,9 @@ export default function FlowDirectionSetting(props) {
- +
diff --git a/src/components/floor-plan/modal/lineProperty/LinePropertySetting.jsx b/src/components/floor-plan/modal/lineProperty/LinePropertySetting.jsx index f5425e67..5b4075f0 100644 --- a/src/components/floor-plan/modal/lineProperty/LinePropertySetting.jsx +++ b/src/components/floor-plan/modal/lineProperty/LinePropertySetting.jsx @@ -3,13 +3,18 @@ import { useRecoilValue } from 'recoil' import { contextPopupPositionState } from '@/store/popupAtom' import { useMessage } from '@/hooks/useMessage' import { usePopup } from '@/hooks/usePopup' -import { useState } from 'react' +import { useState, useEffect } from 'react' +import { useSurfaceShapeBatch } from '@/hooks/surface/useSurfaceShapeBatch' +import { useEvent } from '@/hooks/useEvent' export default function LinePropertySetting(props) { const contextPopupPosition = useRecoilValue(contextPopupPositionState) - const { id, pos = contextPopupPosition } = props + const { id, pos = contextPopupPosition, target } = props const { getMessage } = useMessage() const { closePopup } = usePopup() + const { changeSurfaceLinePropertyEvent, changeSurfaceLineProperty } = useSurfaceShapeBatch() + const { initEvent } = useEvent() + const properties = [ { name: getMessage('eaves.line'), value: 'eaves' }, { name: getMessage('ridge'), value: 'ridge' }, @@ -29,6 +34,14 @@ export default function LinePropertySetting(props) { { name: getMessage('no.setting'), value: 'noSetting' }, ] const [selectedProperty, setSelectedProperty] = useState(null) + + useEffect(() => { + changeSurfaceLinePropertyEvent(target) + return () => { + initEvent() + } + }, []) + return (
@@ -66,7 +79,9 @@ export default function LinePropertySetting(props) {
- +
diff --git a/src/hooks/surface/useSurfaceShapeBatch.js b/src/hooks/surface/useSurfaceShapeBatch.js index d2c6aee7..67ee1874 100644 --- a/src/hooks/surface/useSurfaceShapeBatch.js +++ b/src/hooks/surface/useSurfaceShapeBatch.js @@ -13,6 +13,8 @@ import { usePopup } from '@/hooks/usePopup' import { roofDisplaySelector } from '@/store/settingAtom' import { usePolygon } from '@/hooks/usePolygon' import { fontSelector } from '@/store/fontAtom' +import { slopeSelector } from '@/store/commonAtom' +import { QLine } from '@/components/fabric/QLine' export function useSurfaceShapeBatch() { const { getMessage } = useMessage() @@ -22,6 +24,7 @@ export function useSurfaceShapeBatch() { const canvas = useRecoilValue(canvasState) const globalPitch = useRecoilValue(globalPitchState) const roofDisplay = useRecoilValue(roofDisplaySelector) + const slope = useRecoilValue(slopeSelector(globalPitch)) const { swalFire } = useSwal() const { addCanvasMouseEventListener, initEvent } = useEvent() const { closePopup } = usePopup() @@ -126,6 +129,7 @@ export function useSurfaceShapeBatch() { addCanvasMouseEventListener('mouse:down', (e) => { isDrawing = false obj.set('name', POLYGON_TYPE.ROOF) + obj.set('surfaceId', surfaceId) initEvent() setSurfaceShapePattern(obj, roofDisplay.column) closePopup(id) @@ -580,18 +584,19 @@ export function useSurfaceShapeBatch() { text: '배치면 내용을 전부 삭제하시겠습니까?', type: 'confirm', confirmFn: () => { - canvas?.getObjects().forEach((obj) => { - if ( - obj.name === POLYGON_TYPE.ROOF || - obj.name === BATCH_TYPE.OPENING || - obj.name === BATCH_TYPE.SHADOW || - obj.name === BATCH_TYPE.TRIANGLE_DORMER || - obj.name === BATCH_TYPE.PENTAGON_DORMER || - obj.name === 'lengthText' - ) { - canvas?.remove(obj) - } - }) + // canvas?.getObjects().forEach((obj) => { + // if ( + // obj.name === POLYGON_TYPE.ROOF || + // obj.name === BATCH_TYPE.OPENING || + // obj.name === BATCH_TYPE.SHADOW || + // obj.name === BATCH_TYPE.TRIANGLE_DORMER || + // obj.name === BATCH_TYPE.PENTAGON_DORMER || + // obj.name === 'lengthText' + // ) { + // canvas?.remove(obj) + // } + // }) + canvas.clear() swalFire({ text: '삭제 완료 되었습니다.' }) }, // denyFn: () => { @@ -823,10 +828,159 @@ export function useSurfaceShapeBatch() { canvas.renderAll() } + const surfaceShapeActualSize = () => { + const roofs = canvas.getObjects().filter((obj) => obj.name === 'roof') + let notParallelLines = [] + + const roofArray = [] + + roofs.forEach((obj) => { + const roof = { + id: obj.id, + surfaceId: obj.surfaceId, + targetLines: [], + baseLines: [], + direction: obj.direction, + } + obj.lines.forEach((line) => { + if (obj.direction === 'north' || obj.direction === 'south') { + if (line.y1 !== line.y2) { + roof.targetLines.push(line) + } else { + roof.baseLines.push(line) + } + } else { + if (line.x1 !== line.x2) { + roof.targetLines.push(line) + } else { + roof.baseLines.push(line) + } + } + }) + roofArray.push(roof) + }) + + const slopeRadians = slope.angleValue * (Math.PI / 180) + const tanSlope = Math.tan(slopeRadians) + + roofArray.forEach((roof) => { + roof.targetLines.forEach((line) => { + let calcLength = line.length + + if (roof.surfaceId === 1) { + calcLength = roof.direction === 'north' || roof.direction === 'south' ? Math.abs(line.y1 - line.y2) : Math.abs(line.x1 - line.x2) + } + + const h = calcLength * tanSlope + const resultLength = Math.sqrt(Math.pow(calcLength, 2) + Math.pow(h, 2)) + + line.set({ + attributes: { + ...line.attributes, + actualSize: parseInt((Math.floor(resultLength) * 10).toFixed(0)), + planeSize: parseInt(line.length * 10), + }, + }) + }) + roof.baseLines.forEach((line) => { + line.set({ + attributes: { + ...line.attributes, + actualSize: parseInt((Math.floor(line.length) * 10).toFixed(0)), + planeSize: parseInt(line.length * 10), + }, + }) + }) + }) + } + + const changeSurfaceLinePropertyEvent = (roof) => { + let tmpLines = [] + roof.set({ + selectable: false, + }) + canvas.discardActiveObject() + roof.lines.forEach((obj, index) => { + const tmpLine = new QLine([obj.x1, obj.y1, obj.x2, obj.y2], { + ...obj, + stroke: 'rgb(3, 255, 0)', + strokeWidth: 8, + selectable: true, + name: 'lineProperty', + index: index, + }) + + tmpLines.push(tmpLine) + canvas.add(tmpLine) + }) + + addCanvasMouseEventListener('mouse:down', (e) => { + const selectedLine = e.target + if (selectedLine) { + selectedLine.set({ + stroke: 'red', + name: 'selectedLineProperty', + }) + tmpLines.forEach((line) => { + if (line.index !== selectedLine.index) { + line.set({ + stroke: 'rgb(3, 255, 0)', + name: 'lineProperty', + }) + } + }) + } else { + tmpLines.forEach((line) => { + line.set({ + stroke: 'rgb(3, 255, 0)', + name: 'lineProperty', + }) + }) + } + }) + + canvas.renderAll() + } + + const changeSurfaceLineProperty = (property) => { + console.log(property) + if (!property) { + swalFire({ text: getMessage('modal.line.property.change'), icon: 'error' }) + return + } + + const selectedLine = canvas.getActiveObjects() + if (selectedLine && selectedLine[0].name === 'selectedLineProperty') { + swalFire({ + text: getMessage('modal.line.property.change.confirm'), + type: 'confirm', + confirmFn: () => { + selectedLine.set({ + type: property.value, + }) + }, + }) + } else { + swalFire({ text: getMessage('modal.line.property.change.unselect'), icon: 'error' }) + } + } + + const changeSurfaceFlowDirection = (roof, direction, orientation) => { + roof.set({ + direction: direction, + }) + drawDirectionArrow(roof) + canvas?.renderAll() + } + return { applySurfaceShape, deleteAllSurfacesAndObjects, moveSurfaceShapeBatch, resizeSurfaceShapeBatch, + surfaceShapeActualSize, + changeSurfaceFlowDirection, + changeSurfaceLinePropertyEvent, + changeSurfaceLineProperty, } } diff --git a/src/hooks/useContextMenu.js b/src/hooks/useContextMenu.js index 64892dce..cc8cce69 100644 --- a/src/hooks/useContextMenu.js +++ b/src/hooks/useContextMenu.js @@ -51,7 +51,7 @@ export function useContextMenu() { const [column, setColumn] = useState(null) const { handleZoomClear } = useCanvasEvent() const { moveObjectBatch } = useObjectBatch({}) - const { moveSurfaceShapeBatch } = useSurfaceShapeBatch() + const { moveSurfaceShapeBatch, surfaceShapeActualSize } = useSurfaceShapeBatch() const currentMenuSetting = () => { switch (currentMenu) { case MENU.PLAN_DRAWING: @@ -303,6 +303,11 @@ export function useContextMenu() { case 'roof': setContextMenu([ [ + { + id: 'surfaceShapeActualSize', + name: '면형상 실측', + fn: () => surfaceShapeActualSize(), + }, { id: 'sizeEdit', name: '사이즈 변경', @@ -336,7 +341,7 @@ export function useContextMenu() { { id: 'linePropertyEdit', name: getMessage('contextmenu.line.property.edit'), - component: , + component: , }, { id: 'flowDirectionEdit', diff --git a/src/locales/ko.json b/src/locales/ko.json index a2ef69b3..bfa3cdc5 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -400,6 +400,9 @@ "modal.module.circuit.number.edit": "모듈 일괄 회로 번호 변경", "modal.module.circuit.number.edit.info": "회로 번호를 입력해주세요.", "modal.module.circuit.number": "회로 번호", + "modal.line.property.change": "변경할 속성을 선택해 주세요.", + "modal.line.property.change.unselect": "변경할 라인을 선택해 주세요.", + "modal.line.property.change.confirm": "속성을 변경하시겠습니까?", "common.message.no.data": "No data", "common.message.no.dataDown": "No data to download", "common.message.noData": "No data to display", @@ -495,6 +498,7 @@ "commons.east": "동", "commons.south": "남", "commons.north": "북", + "commons.none": "선택안함", "font.style.normal": "보통", "font.style.italic": "기울임꼴", "font.style.bold": "굵게", From 1527ab35da6ef7c53d8462512e25fba21e588368 Mon Sep 17 00:00:00 2001 From: basssy Date: Mon, 11 Nov 2024 10:28:06 +0900 Subject: [PATCH 47/51] =?UTF-8?q?=EA=B2=AC=EC=A0=81=EC=84=9C=20=EC=A0=9C?= =?UTF-8?q?=ED=92=88=ED=8A=B9=EC=9D=B4=EC=82=AC=ED=95=AD=20=ED=8C=9D?= =?UTF-8?q?=EC=97=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../estimate/popup/ProductFeaturesPop.jsx | 34 ++++++++++++++----- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/src/components/estimate/popup/ProductFeaturesPop.jsx b/src/components/estimate/popup/ProductFeaturesPop.jsx index 428c6a8e..3940065d 100644 --- a/src/components/estimate/popup/ProductFeaturesPop.jsx +++ b/src/components/estimate/popup/ProductFeaturesPop.jsx @@ -1,12 +1,23 @@ 'use client' -import { useState } from 'react' +import { useEffect, useState } from 'react' import { useMessage } from '@/hooks/useMessage' export default function ProductFeaturesPop({ specialNoteList, showProductFeatureData, setProductFeaturesPopupOpen }) { - console.log('위에서 넘어온거::', specialNoteList) - console.log('위에서 넘어온거::', showProductFeatureData) - //split('、') - + const [showSpecialNoteList, setShowSpecialNoteList] = useState([]) const { getMessage } = useMessage() + + useEffect(() => { + let pushData = [] + specialNoteList.map((row) => { + let option = showProductFeatureData.split('、') + option.map((row2) => { + if (row.code === row2) { + pushData.push(row) + } + }) + }) + setShowSpecialNoteList(pushData) + }, [specialNoteList]) + return (
@@ -26,10 +37,15 @@ export default function ProductFeaturesPop({ specialNoteList, showProductFeature
-
-
제목
-
내용
-
+ {showSpecialNoteList.length > 0 && + showSpecialNoteList.map((row) => { + return ( +
+
{row.codeNm}
+
+
+ ) + })}
From ff7bcabe5041646c141d671c8e1f26603e7d3948 Mon Sep 17 00:00:00 2001 From: minsik Date: Mon, 11 Nov 2024 10:29:16 +0900 Subject: [PATCH 48/51] =?UTF-8?q?contextmenu=20component=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/useContextMenu.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/hooks/useContextMenu.js b/src/hooks/useContextMenu.js index 64892dce..32f56fd9 100644 --- a/src/hooks/useContextMenu.js +++ b/src/hooks/useContextMenu.js @@ -176,6 +176,7 @@ export function useContextMenu() { { id: 'sizeEdit', name: getMessage('contextmenu.size.edit'), + component: , }, { id: 'remove', @@ -211,6 +212,7 @@ export function useContextMenu() { { id: 'flowDirectionEdit', name: getMessage('contextmenu.flow.direction.edit'), + component: , }, ], ]) @@ -257,7 +259,6 @@ export function useContextMenu() { }, [currentContextMenu]) useEffect(() => { - console.log('currentObject', currentObject) if (currentObject?.name) { switch (currentObject.name) { case 'triangleDormer': From acba812d881d34dc127a549fe853ddd932e24f0a Mon Sep 17 00:00:00 2001 From: minsik Date: Mon, 11 Nov 2024 10:29:49 +0900 Subject: [PATCH 49/51] =?UTF-8?q?=EB=B3=B4=EC=A1=B0=EC=84=A0=20=EC=8B=A4?= =?UTF-8?q?=EC=B8=A1=EC=B9=98=20=EC=88=98=EC=A0=95=20=EA=B4=80=EB=A0=A8=20?= =?UTF-8?q?=EC=A1=B0=EA=B1=B4=EB=AC=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../roofcover/useRoofAllocationSetting.js | 20 +++++++------------ 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/src/hooks/roofcover/useRoofAllocationSetting.js b/src/hooks/roofcover/useRoofAllocationSetting.js index b99af935..b4118dc1 100644 --- a/src/hooks/roofcover/useRoofAllocationSetting.js +++ b/src/hooks/roofcover/useRoofAllocationSetting.js @@ -107,18 +107,16 @@ export function useRoofAllocationSetting(id) { } }) }) - if (currentObject) { - console.log(currentObject.name) - if (currentObject.name.toLowerCase().includes('line')) { - currentObject.set({ - strokeWidth: 4, - stroke: '#EA10AC', - }) - } + if (currentObject && currentObject.name && !currentObject.name.toLowerCase().includes('text')) { + currentObject.set({ + strokeWidth: 4, + stroke: '#EA10AC', + }) } }, [currentObject]) useEffect(() => { + // canvas.getObjects().filter((obj) => obj.type === 'QLine') const roofBases = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF) if (roofBases.length === 0) { swalFire({ text: '할당할 지붕이 없습니다.' }) @@ -126,10 +124,6 @@ export function useRoofAllocationSetting(id) { } }, []) - useEffect(() => { - console.log('editingLines', editingLines) - }, [editingLines]) - const onAddRoofMaterial = () => { setValues([...values, selectedRoofMaterial]) } @@ -163,7 +157,7 @@ export function useRoofAllocationSetting(id) { const checkInnerLines = () => { const roofBases = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF) // roofPolygon.innerLines let result = false - console.log(roofBases) + roofBases.forEach((roof) => { roof.innerLines.forEach((line) => { if (!line.attributes.actualSize || line.attributes?.actualSize === 0) { From 2d7f8c18e9c6c55d3f7355dfc7cf3ad65824b0c4 Mon Sep 17 00:00:00 2001 From: basssy Date: Mon, 11 Nov 2024 10:55:07 +0900 Subject: [PATCH 50/51] =?UTF-8?q?=EA=B2=AC=EC=A0=81=EC=84=9C=20=EC=95=84?= =?UTF-8?q?=EC=9D=B4=ED=85=9C=20=EC=9E=90=EB=8F=99=EC=99=84=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/estimate/Estimate.jsx | 30 ++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/src/components/estimate/Estimate.jsx b/src/components/estimate/Estimate.jsx index ca7059ec..8c6af884 100644 --- a/src/components/estimate/Estimate.jsx +++ b/src/components/estimate/Estimate.jsx @@ -34,6 +34,9 @@ export default function Estimate({ params }) { //견적특이사항 접고 펼치기 const [hidden, setHidden] = useState(false) + //아이템 자동완성 리스트 + const [displayItemList, setDisplayItemList] = useState([]) + //공통코드 const { findCommonCode } = useCommonCode() const [honorificCodeList, setHonorificCodeList] = useState([]) //경칭 공통코드 @@ -81,6 +84,17 @@ export default function Estimate({ params }) { if (code1 != null) { setHonorificCodeList(code1) } + + //아이템 자동완성 목록 가져오기 + const param = { + saleStoreId: session.storeId, + } + const apiUrl = `/api/display-item/item-list?${queryStringFormatter(param)}` + get({ url: apiUrl }).then((res) => { + if (res.length > 0) { + setDisplayItemList(res) + } + }) }, []) useEffect(() => { @@ -775,19 +789,19 @@ export default function Estimate({ params }) {