Merge branch 'dev' into feature/test-jy
# Conflicts: # src/app/roof2/page.jsx # src/util/canvas-util.js
10656
package-lock.json
generated
Normal file
@ -28,6 +28,7 @@
|
|||||||
"react-draggable": "^4.4.6",
|
"react-draggable": "^4.4.6",
|
||||||
"react-hook-form": "^7.53.0",
|
"react-hook-form": "^7.53.0",
|
||||||
"react-icons": "^5.3.0",
|
"react-icons": "^5.3.0",
|
||||||
|
"react-loading-skeleton": "^3.5.0",
|
||||||
"react-responsive-modal": "^6.4.2",
|
"react-responsive-modal": "^6.4.2",
|
||||||
"recoil": "^0.7.7",
|
"recoil": "^0.7.7",
|
||||||
"sweetalert2": "^11.14.1",
|
"sweetalert2": "^11.14.1",
|
||||||
|
|||||||
6
public/static/images/canvas/img_check_fail.svg
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g id="elements">
|
||||||
|
<path id="Vector" d="M6.73735 6.73726L11.2628 11.2627M11.2628 6.73726L6.73735 11.2627" stroke="white" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path id="Ellipse 1334" d="M17 9C17 4.58172 13.4183 1 9 1C4.58172 1 1 4.58172 1 9C1 13.4183 4.58172 17 9 17C13.4183 17 17 13.4183 17 9Z" stroke="white"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 431 B |
4
public/static/images/canvas/img_check_success.svg
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M5 9.5L7.5 12L13 6" stroke="white" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path d="M17 9C17 4.58172 13.4183 1 9 1C4.58172 1 1 4.58172 1 9C1 13.4183 4.58172 17 9 17C13.4183 17 17 13.4183 17 9Z" stroke="white"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 332 B |
4
public/static/images/canvas/img_edit_ico.svg
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M9.00078 5.7998V12.1998M12.2008 8.9998L5.80078 8.9998" stroke="#141B34" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path d="M17 9C17 4.58172 13.4183 1 9 1C4.58172 1 1 4.58172 1 9C1 13.4183 4.58172 17 9 17C13.4183 17 17 13.4183 17 9Z" stroke="#141B34"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 371 B |
@ -1,3 +1,3 @@
|
|||||||
<svg width="54" height="34" viewBox="0 0 54 34" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg width="20" height="12" viewBox="0 0 20 12" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path d="M27 0.804011L52.9645 33.5H1.03554L27 0.804011Z" stroke="white"/>
|
<path d="M10 1.56205L17.865 11H2.13504L10 1.56205Z" stroke="white" stroke-width="2"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 177 B After Width: | Height: | Size: 189 B |
@ -1,3 +1,3 @@
|
|||||||
<svg width="54" height="44" viewBox="0 0 54 44" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg width="20" height="17" viewBox="0 0 20 17" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path d="M43.6009 0.5L53.3736 43.5H0.5V13.537H21.9375H22.4375V13.037V0.5H43.6009Z" stroke="white"/>
|
<path d="M15.4907 1L18.7587 16H1V5.63636H8.14815H9.14815V4.63636V1H15.4907Z" stroke="white" stroke-width="2"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 203 B After Width: | Height: | Size: 214 B |
@ -1,3 +1,3 @@
|
|||||||
<svg width="54" height="44" viewBox="0 0 54 44" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg width="20" height="17" viewBox="0 0 20 17" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path d="M10.3991 43.5H53.5V25.537H29.0625H28.5625V25.037V0.5H0.626389L10.3991 43.5Z" stroke="white"/>
|
<path d="M4.5093 16H19V10H10H8.958L9.00085 8.95888L9.32837 1H1.24132L4.5093 16Z" stroke="white" stroke-width="2"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 206 B After Width: | Height: | Size: 218 B |
@ -1,3 +1,3 @@
|
|||||||
<svg width="57" height="41" viewBox="0 0 57 41" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg width="22" height="16" viewBox="0 0 22 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path d="M30.384 8.3129L30.5329 8.53093H30.7969H39.3543L56.172 40.5H0.896303L25.3336 0.917553L30.384 8.3129Z" stroke="white"/>
|
<path d="M10.8546 3.62169L11.1523 4.0594H11.6816H14.4443L20.3269 15H1.76631L9.65389 1.8558L10.8546 3.62169Z" stroke="white" stroke-width="2"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 230 B After Width: | Height: | Size: 246 B |
@ -1,3 +1,3 @@
|
|||||||
<svg width="54" height="41" viewBox="0 0 54 41" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg width="20" height="16" viewBox="0 0 20 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path d="M28.7562 8.30253L28.9042 8.53127L29.1766 8.53093L53.5 8.50062V40.5H0.871685L24.0017 0.953657L28.7562 8.30253Z" stroke="white"/>
|
<path d="M11.083 3.75037L11.379 4.06002L11.8074 4.0594L19 4.04906V15H1.69884L9.09691 1.67251L11.083 3.75037Z" stroke="white" stroke-width="2"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 240 B After Width: | Height: | Size: 247 B |
@ -1,3 +1,3 @@
|
|||||||
<svg width="54" height="34" viewBox="0 0 54 34" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg width="20" height="13" viewBox="0 0 20 13" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path d="M17.2929 33.5H0.5V0.5H53.5V33.5H36.7071L27.3536 24.1464L27 23.7929L26.6464 24.1464L17.2929 33.5Z" stroke="white"/>
|
<path d="M6.05791 12H1V1H19V12H13.9421L10.7183 8.67188L10 7.93037L9.28173 8.67188L6.05791 12Z" stroke="white" stroke-width="2"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 227 B After Width: | Height: | Size: 232 B |
@ -1,3 +1,3 @@
|
|||||||
<svg width="40" height="50" viewBox="0 0 40 50" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg width="15" height="19" viewBox="0 0 15 19" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path d="M20 0.64603L39.5 16.6006V49.5H0.5V16.6006L20 0.64603Z" stroke="white"/>
|
<path d="M7.5 1.299L14 6.68809V18H1V6.68809L7.5 1.299Z" stroke="white" stroke-width="2"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 184 B After Width: | Height: | Size: 193 B |
@ -1,5 +1,3 @@
|
|||||||
<svg width="54" height="42" viewBox="0 0 54 42" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg width="20" height="16" viewBox="0 0 20 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path d="M0.971595 41.5L10.2573 28.5H44.727L53.0842 41.5H0.971595Z" fill="#313131" stroke="white"/>
|
<path d="M3.96963 10.3554L4.07692 10.1429V9.90476V1H15.9231V9.90476V10.1429L16.0304 10.3554L18.375 15H1.625L3.96963 10.3554Z" stroke="white" stroke-width="2"/>
|
||||||
<path d="M10.5 0.5H44.5V28.5H10.5V0.5Z" fill="#313131" stroke="white"/>
|
|
||||||
<rect x="11" y="28" width="33" height="1" fill="#313131"/>
|
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 334 B After Width: | Height: | Size: 263 B |
@ -1,3 +1,3 @@
|
|||||||
<svg width="58" height="39" viewBox="0 0 58 39" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg width="22" height="15" viewBox="0 0 22 15" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path d="M57.4251 17.0318L46.691 38.5H0.865706L22.7888 0.5H46.728L57.4251 17.0318Z" stroke="white"/>
|
<path d="M20.8541 6.14406L17.5432 14H1.70065L8.93284 1H16.9517L20.8541 6.14406Z" stroke="white" stroke-width="2"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 204 B After Width: | Height: | Size: 218 B |
@ -1,3 +1,3 @@
|
|||||||
<svg width="58" height="47" viewBox="0 0 58 47" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg width="22" height="18" viewBox="0 0 22 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path d="M57.339 20.1115L40.724 46.5H0.962002L33.1033 0.72297L57.339 20.1115Z" stroke="white"/>
|
<path d="M20.6552 7.73365L14.6298 17H1.88045L12.3752 1.43676L20.6552 7.73365Z" stroke="white" stroke-width="2"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 199 B After Width: | Height: | Size: 216 B |
@ -1,3 +1,3 @@
|
|||||||
<svg width="54" height="34" viewBox="0 0 54 34" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg width="20" height="12" viewBox="0 0 20 12" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<rect x="0.5" y="0.5" width="53" height="33" fill="#313131" stroke="white"/>
|
<rect x="1" y="1" width="18" height="10" stroke="white" stroke-width="2"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 180 B After Width: | Height: | Size: 178 B |
@ -1,3 +1,3 @@
|
|||||||
<svg width="54" height="34" viewBox="0 0 54 34" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg width="20" height="12" viewBox="0 0 20 12" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path d="M0.654784 33.5L9.66306 0.5H44.3369L53.3452 33.5H0.654784Z" stroke="white"/>
|
<path d="M3.98369 1.72462C4.10657 1.29565 4.4988 1 4.94502 1H15.055C15.5012 1 15.8934 1.29565 16.0163 1.72462L18.308 9.72462C18.491 10.3636 18.0113 11 17.3466 11H2.65336C1.98869 11 1.50899 10.3636 1.69202 9.72462L3.98369 1.72462Z" stroke="white" stroke-width="2"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 188 B After Width: | Height: | Size: 368 B |
@ -1,3 +1,3 @@
|
|||||||
<svg width="44" height="44" viewBox="0 0 44 44" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path d="M43.5 43.5H1.20711L43.5 1.20711V43.5Z" stroke="white"/>
|
<path d="M2.12132 11.2929L11.2929 2.12132C11.9229 1.49136 13 1.93752 13 2.82843V12C13 12.5523 12.5523 13 12 13H2.82843C1.93752 13 1.49136 11.9229 2.12132 11.2929Z" stroke="white" stroke-width="2"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 168 B After Width: | Height: | Size: 301 B |
@ -1,3 +1,3 @@
|
|||||||
<svg width="34" height="44" viewBox="0 0 34 44" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg width="13" height="17" viewBox="0 0 13 17" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path d="M33.5 1.04958V43.5H0.5V27.8255L33.5 1.04958Z" stroke="white"/>
|
<path d="M12 2.11305V16H1V11.132L12 2.11305Z" stroke="white" stroke-width="2"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 175 B After Width: | Height: | Size: 183 B |
@ -1,3 +1,3 @@
|
|||||||
<svg width="54" height="34" viewBox="0 0 54 34" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg width="20" height="13" viewBox="0 0 20 13" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path d="M0.6187 33.5L7.70137 0.5H53.3813L46.2986 33.5H0.6187Z" stroke="white"/>
|
<path d="M1.22928 12L3.51619 1H18.7707L16.4838 12H1.22928Z" stroke="white" stroke-width="2"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 184 B After Width: | Height: | Size: 197 B |
@ -1,3 +1,3 @@
|
|||||||
<svg width="54" height="34" viewBox="0 0 54 34" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg width="20" height="13" viewBox="0 0 20 13" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path d="M10 23.5H9.5V24V33.5H0.5V0.5H53.5V33.5H44.5V24V23.5H44H10Z" stroke="white"/>
|
<path d="M6.18518 8.17647H5.18518V9.17647V12H1V1H19V12H14.8148V9.17647V8.17647H13.8148H6.18518Z" stroke="white" stroke-width="2"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 189 B After Width: | Height: | Size: 234 B |
@ -1,3 +1,3 @@
|
|||||||
<svg width="54" height="44" viewBox="0 0 54 44" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg width="20" height="17" viewBox="0 0 20 17" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path d="M22.4375 13.037V0.5H53.5V43.5H0.5V13.537H21.9375H22.4375V13.037Z" stroke="white"/>
|
<path d="M9.125 5V1H19V16H1V6H8.125H9.125V5Z" stroke="white" stroke-width="2"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 195 B After Width: | Height: | Size: 183 B |
@ -1,3 +1,3 @@
|
|||||||
<svg width="54" height="44" viewBox="0 0 54 44" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg width="20" height="17" viewBox="0 0 20 17" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path d="M30.4375 25.037V0.5H53.5V43.5H1.03302L15.242 25.537H29.9375H30.4375V25.037Z" stroke="white"/>
|
<path d="M12.1111 9.27023L12.0905 1H19V16H1.8753L5.71843 10.2727H11.1111H12.1136L12.1111 9.27023Z" stroke="white" stroke-width="2"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 206 B After Width: | Height: | Size: 236 B |
@ -1,11 +1,5 @@
|
|||||||
<svg width="23" height="24" viewBox="0 0 23 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<g id="ico">
|
<rect x="0.5" y="0.5" width="19" height="19" rx="9.5" fill="white"/>
|
||||||
<circle id="Ellipse 2012" cx="11.5" cy="12" r="11.5" fill="#45576F"/>
|
<rect x="0.5" y="0.5" width="19" height="19" rx="9.5" stroke="#0191C9"/>
|
||||||
<g id="elements">
|
<path d="M13.186 5.7898C12.6312 5.20223 11.7307 5.20223 11.1759 5.7898L6.99193 10.2206C6.03462 11.2344 6.03462 12.8767 6.99193 13.8905C7.94924 14.9043 9.50003 14.9043 10.4573 13.8905L13.9136 10.2303C14.1615 9.96779 14.5663 9.96779 14.8141 10.2303C15.062 10.4928 15.062 10.9214 14.8141 11.1839L11.3578 14.8441C9.90251 16.3853 7.54676 16.3853 6.09147 14.8441C4.63618 13.303 4.63618 10.8082 6.09147 9.26705L10.2754 4.8362C11.3282 3.72127 13.0337 3.72127 14.0865 4.8362C15.1393 5.95114 15.1393 7.75719 14.0865 8.87212L10.0844 13.1103C9.43409 13.799 8.379 13.799 7.72867 13.1103C7.07834 12.4216 7.07834 11.3043 7.72867 10.6156L11.0031 7.14795C11.2509 6.88547 11.6557 6.88547 11.9035 7.14795C12.1514 7.41042 12.1514 7.83906 11.9035 8.10154L8.62913 11.5692C8.47678 11.7305 8.47678 11.9954 8.62913 12.1567C8.78148 12.3181 9.03161 12.3181 9.18396 12.1567L13.186 7.91853C13.7408 7.33096 13.7408 6.37736 13.186 5.7898Z" fill="#0191C9" stroke="white" stroke-width="0.5"/>
|
||||||
<path id="Vector" d="M9.66678 12.8193C9.7612 12.9739 9.87323 13.1202 10.0029 13.2552C10.8079 14.093 12.0349 14.224 12.9718 13.6481C13.1454 13.5414 13.3091 13.4104 13.4582 13.2552L15.6178 11.0076C16.572 10.0145 16.572 8.40447 15.6178 7.41141C14.6637 6.41836 13.1166 6.41836 12.1625 7.41142L11.6868 7.90648" stroke="white" stroke-width="1.5" stroke-linecap="round"/>
|
|
||||||
<path id="Vector_2" d="M10.313 16.0933L9.83718 16.5885C8.88301 17.5816 7.33598 17.5816 6.3818 16.5885C5.42762 15.5955 5.42762 13.9854 6.3818 12.9924L8.54141 10.7448C9.49559 9.75174 11.0426 9.75174 11.9968 10.7448C12.1264 10.8797 12.2384 11.026 12.3328 11.1806" stroke="white" stroke-width="1.5" stroke-linecap="round"/>
|
|
||||||
<path id="Vector_3" d="M17.0003 14.6666H15.6143M13.6669 18L13.6669 16.614" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
|
||||||
<path id="Vector_4" d="M5 9.33333H6.38593M8.33333 6L8.33333 7.38593" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
7
public/static/images/sub/change_ico.svg
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<rect x="0.5" y="0.5" width="19" height="19" rx="9.5" fill="white"/>
|
||||||
|
<rect x="0.5" y="0.5" width="19" height="19" rx="9.5" stroke="#909000"/>
|
||||||
|
<path d="M4 10C4 13.3137 6.68629 16 10 16C13.3137 16 16 13.3137 16 10C16 6.68629 13.3137 4 10 4" stroke="#909000" stroke-linecap="round"/>
|
||||||
|
<path d="M5.58914 5.8473C5.67215 5.75932 5.75769 5.67375 5.84566 5.59071M7.5684 4.43768C7.67731 4.38873 7.78788 4.34282 7.9 4.30005M4.3 7.90005C4.34317 7.78681 4.38955 7.67516 4.43904 7.5652" stroke="#909000" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path d="M9.99999 7.59961V12.3996M12.4 9.99961L7.59999 9.99961" stroke="#909000" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 772 B |
@ -1,4 +1,5 @@
|
|||||||
<svg width="15" height="16" viewBox="0 0 15 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<circle cx="7" cy="7.5" r="6.5" fill="white" stroke="#F16A6A"/>
|
<rect x="0.5" y="0.5" width="19" height="19" rx="9.5" fill="white"/>
|
||||||
<path d="M6.507 9.228L6.276 5.169L6.221 3.629H7.849L7.794 5.169L7.563 9.228H6.507ZM7.035 12.154C6.74167 12.154 6.49967 12.0513 6.309 11.846C6.12567 11.6407 6.034 11.3913 6.034 11.098C6.034 10.79 6.12567 10.537 6.309 10.339C6.49967 10.141 6.74167 10.042 7.035 10.042C7.32833 10.042 7.56667 10.141 7.75 10.339C7.94067 10.537 8.036 10.79 8.036 11.098C8.036 11.3913 7.94067 11.6407 7.75 11.846C7.56667 12.0513 7.32833 12.154 7.035 12.154Z" fill="#F16A6A"/>
|
<rect x="0.5" y="0.5" width="19" height="19" rx="9.5" stroke="#F16A6A"/>
|
||||||
|
<path d="M9.47136 11.228L9.24036 7.169L9.18536 5.629H10.8134L10.7584 7.169L10.5274 11.228H9.47136ZM9.99936 14.154C9.70602 14.154 9.46402 14.0513 9.27336 13.846C9.09002 13.6407 8.99836 13.3913 8.99836 13.098C8.99836 12.79 9.09002 12.537 9.27336 12.339C9.46402 12.141 9.70602 12.042 9.99936 12.042C10.2927 12.042 10.531 12.141 10.7144 12.339C10.905 12.537 11.0004 12.79 11.0004 13.098C11.0004 13.3913 10.905 13.6407 10.7144 13.846C10.531 14.0513 10.2927 14.154 9.99936 14.154Z" fill="#F16A6A"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 620 B After Width: | Height: | Size: 738 B |
6
public/static/images/sub/open_ico.svg
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<rect x="0.5" y="0.5" width="19" height="19" rx="9.5" fill="white"/>
|
||||||
|
<rect x="0.5" y="0.5" width="19" height="19" rx="9.5" stroke="#3BBB48"/>
|
||||||
|
<path d="M11.3571 4.95962C10.7174 4.31987 10.3975 4 10 4C9.60251 4 9.28264 4.31987 8.64289 4.95962C8.25899 5.34352 7.87857 5.52175 7.33125 5.52175C6.85336 5.52175 6.17346 5.42907 5.8 5.80567C5.4295 6.17929 5.52177 6.85639 5.52177 7.33123C5.52177 7.87857 5.34352 8.25899 4.95961 8.6429C4.31987 9.28264 4.00001 9.60251 4 9.99999C4.00001 10.3975 4.31988 10.7174 4.95963 11.3571C5.38969 11.7872 5.52177 12.0649 5.52177 12.6687C5.52177 13.1466 5.42908 13.8265 5.80569 14.2C6.17931 14.5705 6.85641 14.4782 7.33124 14.4782C7.91409 14.4782 8.19477 14.5922 8.61074 15.0082C8.96495 15.3624 9.43978 16 10 16C10.5602 16 11.0351 15.3624 11.3893 15.0082C11.8052 14.5922 12.0859 14.4782 12.6688 14.4782C13.1436 14.4782 13.8207 14.5705 14.1943 14.2M15.0404 8.6429C15.6801 9.28264 16 9.60251 16 9.99999C16 10.3975 15.6801 10.7174 15.0404 11.3571C14.6103 11.7871 14.4782 12.0649 14.4782 12.6687C14.4782 13.1466 14.5709 13.8265 14.1943 14.2M14.1943 14.2H14.2" stroke="#3BBB48" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path d="M7.9 8.49998L10 10.6L15.4002 4.59998" stroke="#3BBB48" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.3 KiB |
@ -1,15 +1,28 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
// import { useEffect } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { ErrorBoundary } from 'next/dist/client/components/error-boundary'
|
import { ErrorBoundary } from 'next/dist/client/components/error-boundary'
|
||||||
import { useCommonCode } from '@/hooks/common/useCommonCode'
|
import { useCommonCode } from '@/hooks/common/useCommonCode'
|
||||||
|
import { usePlan } from '@/hooks/usePlan'
|
||||||
import ServerError from './error'
|
import ServerError from './error'
|
||||||
|
|
||||||
import '@/styles/common.scss'
|
import '@/styles/common.scss'
|
||||||
|
|
||||||
export const QcastProvider = ({ children }) => {
|
export const QcastProvider = ({ children }) => {
|
||||||
|
const [planSave, setPlanSave] = useState(false)
|
||||||
|
const { currentCanvasPlan, modifiedPlans, checkUnsavedCanvasPlan } = usePlan()
|
||||||
const { commonCode, findCommonCode } = useCommonCode()
|
const { commonCode, findCommonCode } = useCommonCode()
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const targetElement = document.getElementById('canvas')
|
||||||
|
if (!targetElement && currentCanvasPlan?.id && planSave) {
|
||||||
|
setPlanSave((prev) => !prev)
|
||||||
|
checkUnsavedCanvasPlan(currentCanvasPlan.userId)
|
||||||
|
} else if (targetElement && currentCanvasPlan?.id) {
|
||||||
|
setPlanSave(true)
|
||||||
|
}
|
||||||
|
}, [modifiedPlans])
|
||||||
|
|
||||||
// useEffect(() => {
|
// useEffect(() => {
|
||||||
// console.log('commonCode', commonCode)
|
// console.log('commonCode', commonCode)
|
||||||
// console.log(findCommonCode(113600))
|
// console.log(findCommonCode(113600))
|
||||||
|
|||||||
12
src/app/floor-plan/estimate/[mid]/[pid]/page.jsx
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import Estimate from '@/components/estimate/Estimate'
|
||||||
|
|
||||||
|
export default function EstimatePage({ params }) {
|
||||||
|
//floor-plan/estimate/mid/pid
|
||||||
|
//mid :5 견적탭
|
||||||
|
//pid : 넘어온 플랜번호
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Estimate params={params} />
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -1,11 +1,17 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
import FloorPlan from '@/components/floor-plan/FloorPlan'
|
||||||
import { FloorPlanProvider } from './FloorPlanProvider'
|
import { FloorPlanProvider } from './FloorPlanProvider'
|
||||||
|
import CanvasLayout from '@/components/floor-plan/CanvasLayout'
|
||||||
|
|
||||||
export default function FloorPlanLayout({ children }) {
|
export default function FloorPlanLayout({ children }) {
|
||||||
console.log('FloorPlanLayout')
|
console.log('FloorPlanLayout')
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<FloorPlanProvider>{children}</FloorPlanProvider>
|
<FloorPlanProvider>
|
||||||
|
<FloorPlan>
|
||||||
|
<CanvasLayout>{children}</CanvasLayout>
|
||||||
|
</FloorPlan>
|
||||||
|
</FloorPlanProvider>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
import FloorPlan from '@/components/floor-plan/FloorPlan'
|
import CanvasFrame from '@/components/floor-plan/CanvasFrame'
|
||||||
|
|
||||||
export default function FloorPlanPage() {
|
export default function FloorPlanPage() {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<FloorPlan />
|
<CanvasFrame />
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -46,6 +46,7 @@ export default async function RootLayout({ children }) {
|
|||||||
storeLvl: session.storeLvl,
|
storeLvl: session.storeLvl,
|
||||||
groupId: session.groupId,
|
groupId: session.groupId,
|
||||||
pwdInitYn: session.pwdInitYn,
|
pwdInitYn: session.pwdInitYn,
|
||||||
|
custCd: session.custCd,
|
||||||
isLoggedIn: session.isLoggedIn,
|
isLoggedIn: session.isLoggedIn,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
import { fabric } from 'fabric'
|
||||||
|
|
||||||
export const MENU = {
|
export const MENU = {
|
||||||
PLAN_DRAWING: 'planDrawing',
|
PLAN_DRAWING: 'planDrawing',
|
||||||
INITIAL_CANVAS_SETTING: 'initialCanvasSetting', // 배치면 초기설정
|
INITIAL_CANVAS_SETTING: 'initialCanvasSetting', // 배치면 초기설정
|
||||||
@ -118,3 +120,45 @@ export const POLYGON_TYPE = {
|
|||||||
WALL: 'wall',
|
WALL: 'wall',
|
||||||
TRESTLE: 'trestle',
|
TRESTLE: 'trestle',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const SAVE_KEY = [
|
||||||
|
'selectable',
|
||||||
|
'name',
|
||||||
|
'parentId',
|
||||||
|
'id',
|
||||||
|
'length',
|
||||||
|
'idx',
|
||||||
|
'direction',
|
||||||
|
'parentDirection',
|
||||||
|
'lines',
|
||||||
|
'points',
|
||||||
|
'lockMovementX',
|
||||||
|
'lockMovementY',
|
||||||
|
'lockRotation',
|
||||||
|
'lockScalingX',
|
||||||
|
'lockScalingY',
|
||||||
|
'opacity',
|
||||||
|
'cells',
|
||||||
|
'maxX',
|
||||||
|
'maxY',
|
||||||
|
'minX',
|
||||||
|
'minY',
|
||||||
|
'x',
|
||||||
|
'y',
|
||||||
|
'x1',
|
||||||
|
'x2',
|
||||||
|
'y1',
|
||||||
|
'y2',
|
||||||
|
'attributes',
|
||||||
|
'stickeyPoint',
|
||||||
|
'text',
|
||||||
|
'pitch',
|
||||||
|
'uuid',
|
||||||
|
'originText',
|
||||||
|
'groupYn',
|
||||||
|
'groupName',
|
||||||
|
'lineDirection',
|
||||||
|
'groupId',
|
||||||
|
]
|
||||||
|
|
||||||
|
export const OBJECT_PROTOTYPE = [fabric.Line.prototype, fabric.Polygon.prototype, fabric.Triangle.prototype]
|
||||||
|
|||||||
@ -1,20 +1,138 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
|
import { useRef } from 'react'
|
||||||
import { useAxios } from '@/hooks/useAxios'
|
import { useAxios } from '@/hooks/useAxios'
|
||||||
import { useRouter } from 'next/navigation'
|
import { useRouter } from 'next/navigation'
|
||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import Cookies from 'js-cookie'
|
import Cookies from 'js-cookie'
|
||||||
|
|
||||||
|
import { isObjectNotEmpty, inputTelNumberCheck, inputNumberCheck } from '@/util/common-utils'
|
||||||
|
|
||||||
export default function Join() {
|
export default function Join() {
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
const { promisePost } = useAxios()
|
const { promisePost } = useAxios()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
|
const storeQcastNmRef = useRef()
|
||||||
|
const storeQcastNmKanaRef = useRef()
|
||||||
|
const postCdRef = useRef()
|
||||||
|
const addrRef = useRef()
|
||||||
|
const telNoRef = useRef()
|
||||||
|
const faxRef = useRef()
|
||||||
|
const userNmRef = useRef()
|
||||||
|
const userIdRef = useRef()
|
||||||
|
const emailRef = useRef()
|
||||||
|
const userTelNoRef = useRef()
|
||||||
|
const userFaxRef = useRef()
|
||||||
|
|
||||||
|
// 가입 신청 유효성 검사
|
||||||
|
const joinValidation = (formData) => {
|
||||||
|
// 판매대리점 정보 - 판매대리점명
|
||||||
|
const storeQcastNm = formData.get('storeQcastNm')
|
||||||
|
if (!isObjectNotEmpty(storeQcastNm)) {
|
||||||
|
alert(getMessage('common.message.required.data', [getMessage('join.sub1.storeQcastNm')]))
|
||||||
|
storeQcastNmRef.current.focus()
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 판매대리점 정보 - 판매대리점명 후리가나
|
||||||
|
const storeQcastNmKana = formData.get('storeQcastNmKana')
|
||||||
|
if (!isObjectNotEmpty(storeQcastNmKana)) {
|
||||||
|
alert(getMessage('common.message.required.data', [getMessage('join.sub1.storeQcastNmKana')]))
|
||||||
|
storeQcastNmKanaRef.current.focus()
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 판매대리점 정보 - 우편번호
|
||||||
|
const postCd = formData.get('postCd')
|
||||||
|
if (!isObjectNotEmpty(postCd)) {
|
||||||
|
alert(getMessage('common.message.required.data', [getMessage('join.sub1.postCd')]))
|
||||||
|
postCdRef.current.focus()
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 판매대리점 정보 - 주소
|
||||||
|
const addr = formData.get('addr')
|
||||||
|
if (!isObjectNotEmpty(addr)) {
|
||||||
|
alert(getMessage('common.message.required.data', [getMessage('join.sub1.addr')]))
|
||||||
|
addrRef.current.focus()
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 판매대리점 정보 - 전화번호
|
||||||
|
const telNo = formData.get('telNo')
|
||||||
|
if (!isObjectNotEmpty(telNo)) {
|
||||||
|
alert(getMessage('common.message.required.data', [getMessage('join.sub1.telNo')]))
|
||||||
|
telNoRef.current.focus()
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 판매대리점 정보 - FAX 번호
|
||||||
|
const fax = formData.get('fax')
|
||||||
|
if (!isObjectNotEmpty(fax)) {
|
||||||
|
alert(getMessage('common.message.required.data', [getMessage('join.sub1.fax')]))
|
||||||
|
faxRef.current.focus()
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 담당자 정보 - 담당자명
|
||||||
|
const userNm = formData.get('userNm')
|
||||||
|
if (!isObjectNotEmpty(userNm)) {
|
||||||
|
alert(getMessage('common.message.required.data', [getMessage('join.sub2.userNm')]))
|
||||||
|
userNmRef.current.focus()
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 담당자 정보 - 신청 ID
|
||||||
|
const userId = formData.get('userId')
|
||||||
|
if (!isObjectNotEmpty(userId)) {
|
||||||
|
alert(getMessage('common.message.required.data', [getMessage('join.sub2.userId')]))
|
||||||
|
userIdRef.current.focus()
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 담당자 정보 - 이메일 주소
|
||||||
|
const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/
|
||||||
|
|
||||||
|
const email = formData.get('email')
|
||||||
|
if (!isObjectNotEmpty(email)) {
|
||||||
|
alert(getMessage('common.message.required.data', [getMessage('join.sub2.email')]))
|
||||||
|
emailRef.current.focus()
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
// 이메일 정규식 검사
|
||||||
|
if (!emailRegex.test(email)) {
|
||||||
|
alert(getMessage('join.validation.check1', [getMessage('join.sub2.email')]))
|
||||||
|
emailRef.current.focus()
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 담당자 정보 - 전화번호
|
||||||
|
const userTelNo = formData.get('userTelNo')
|
||||||
|
if (!isObjectNotEmpty(userTelNo)) {
|
||||||
|
alert(getMessage('common.message.required.data', [getMessage('join.sub2.telNo')]))
|
||||||
|
userTelNoRef.current.focus()
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 담당자 정보 - FAX 번호
|
||||||
|
const userFax = formData.get('userFax')
|
||||||
|
if (!isObjectNotEmpty(userFax)) {
|
||||||
|
alert(getMessage('common.message.required.data', [getMessage('join.sub2.fax')]))
|
||||||
|
userFaxRef.current.focus()
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// 가입 신청
|
// 가입 신청
|
||||||
const joinProcess = async (e) => {
|
const joinProcess = async (e) => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
const formData = new FormData(e.target)
|
const formData = new FormData(e.target)
|
||||||
|
|
||||||
|
if (joinValidation(formData)) {
|
||||||
|
if (confirm(getMessage('join.complete.save.confirm'))) {
|
||||||
const param = {
|
const param = {
|
||||||
storeQcastNm: formData.get('storeQcastNm'),
|
storeQcastNm: formData.get('storeQcastNm'),
|
||||||
storeQcastNmKana: formData.get('storeQcastNmKana'),
|
storeQcastNmKana: formData.get('storeQcastNmKana'),
|
||||||
@ -49,6 +167,8 @@ export default function Join() {
|
|||||||
alert(error.response.data.message)
|
alert(error.response.data.message)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="center-page-wrap">
|
<div className="center-page-wrap">
|
||||||
@ -71,6 +191,7 @@ export default function Join() {
|
|||||||
<col />
|
<col />
|
||||||
</colgroup>
|
</colgroup>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
{/* 판매대리점명 */}
|
||||||
<tr>
|
<tr>
|
||||||
<th>
|
<th>
|
||||||
{getMessage('join.sub1.storeQcastNm')} <span className="important">*</span>
|
{getMessage('join.sub1.storeQcastNm')} <span className="important">*</span>
|
||||||
@ -81,14 +202,16 @@ export default function Join() {
|
|||||||
type="text"
|
type="text"
|
||||||
id="storeQcastNm"
|
id="storeQcastNm"
|
||||||
name="storeQcastNm"
|
name="storeQcastNm"
|
||||||
required
|
|
||||||
alt={getMessage('join.sub1.storeQcastNm')}
|
alt={getMessage('join.sub1.storeQcastNm')}
|
||||||
className="input-light"
|
className="input-light"
|
||||||
placeholder={getMessage('join.sub1.storeQcastNm_placeholder')}
|
placeholder={getMessage('join.sub1.storeQcastNm_placeholder')}
|
||||||
|
maxLength={30}
|
||||||
|
ref={storeQcastNmRef}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
{/* 판매대리점명 후리가나 */}
|
||||||
<tr>
|
<tr>
|
||||||
<th>
|
<th>
|
||||||
{getMessage('join.sub1.storeQcastNmKana')} <span className="important">*</span>
|
{getMessage('join.sub1.storeQcastNmKana')} <span className="important">*</span>
|
||||||
@ -99,13 +222,15 @@ export default function Join() {
|
|||||||
type="text"
|
type="text"
|
||||||
id="storeQcastNmKana"
|
id="storeQcastNmKana"
|
||||||
name="storeQcastNmKana"
|
name="storeQcastNmKana"
|
||||||
required
|
|
||||||
className="input-light"
|
className="input-light"
|
||||||
placeholder={getMessage('join.sub1.storeQcastNmKana_placeholder')}
|
placeholder={getMessage('join.sub1.storeQcastNmKana_placeholder')}
|
||||||
|
maxLength={30}
|
||||||
|
ref={storeQcastNmKanaRef}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
{/* 우편번호/주소 */}
|
||||||
<tr>
|
<tr>
|
||||||
<th>
|
<th>
|
||||||
{getMessage('join.sub1.postCd')}/{getMessage('join.sub1.addr')} <span className="important">*</span>
|
{getMessage('join.sub1.postCd')}/{getMessage('join.sub1.addr')} <span className="important">*</span>
|
||||||
@ -117,9 +242,11 @@ export default function Join() {
|
|||||||
type="text"
|
type="text"
|
||||||
id="postCd"
|
id="postCd"
|
||||||
name="postCd"
|
name="postCd"
|
||||||
required
|
|
||||||
className="input-light"
|
className="input-light"
|
||||||
placeholder={getMessage('join.sub1.postCd_placeholder')}
|
placeholder={getMessage('join.sub1.postCd_placeholder')}
|
||||||
|
onChange={inputNumberCheck}
|
||||||
|
maxLength={7}
|
||||||
|
ref={postCdRef}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="input-wrap" style={{ width: '495px' }}>
|
<div className="input-wrap" style={{ width: '495px' }}>
|
||||||
@ -127,14 +254,16 @@ export default function Join() {
|
|||||||
type="text"
|
type="text"
|
||||||
id="addr"
|
id="addr"
|
||||||
name="addr"
|
name="addr"
|
||||||
required
|
|
||||||
className="input-light"
|
className="input-light"
|
||||||
placeholder={getMessage('join.sub1.addr_placeholder')}
|
placeholder={getMessage('join.sub1.addr_placeholder')}
|
||||||
|
maxLength={50}
|
||||||
|
ref={addrRef}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
{/* 전화번호 */}
|
||||||
<tr>
|
<tr>
|
||||||
<th>
|
<th>
|
||||||
{getMessage('join.sub1.telNo')} <span className="important">*</span>
|
{getMessage('join.sub1.telNo')} <span className="important">*</span>
|
||||||
@ -145,13 +274,16 @@ export default function Join() {
|
|||||||
type="text"
|
type="text"
|
||||||
id="telNo"
|
id="telNo"
|
||||||
name="telNo"
|
name="telNo"
|
||||||
required
|
|
||||||
className="input-light"
|
className="input-light"
|
||||||
placeholder={getMessage('join.sub1.telNo_placeholder')}
|
placeholder={getMessage('join.sub1.telNo_placeholder')}
|
||||||
></input>
|
maxLength={15}
|
||||||
|
onChange={inputTelNumberCheck}
|
||||||
|
ref={telNoRef}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
{/* FAX 번호 */}
|
||||||
<tr>
|
<tr>
|
||||||
<th>
|
<th>
|
||||||
{getMessage('join.sub1.fax')} <span className="important">*</span>
|
{getMessage('join.sub1.fax')} <span className="important">*</span>
|
||||||
@ -162,18 +294,21 @@ export default function Join() {
|
|||||||
type="text"
|
type="text"
|
||||||
id="fax"
|
id="fax"
|
||||||
name="fax"
|
name="fax"
|
||||||
required
|
|
||||||
className="input-light"
|
className="input-light"
|
||||||
placeholder={getMessage('join.sub1.fax_placeholder')}
|
placeholder={getMessage('join.sub1.fax_placeholder')}
|
||||||
></input>
|
maxLength={15}
|
||||||
|
onChange={inputTelNumberCheck}
|
||||||
|
ref={faxRef}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
{/* 법인번호 */}
|
||||||
<tr>
|
<tr>
|
||||||
<th>{getMessage('join.sub1.bizNo')}</th>
|
<th>{getMessage('join.sub1.bizNo')}</th>
|
||||||
<td>
|
<td>
|
||||||
<div className="input-wrap" style={{ width: '200px' }}>
|
<div className="input-wrap" style={{ width: '200px' }}>
|
||||||
<input type="text" id="bizNo" name="bizNo" className="input-light" />
|
<input type="text" id="bizNo" name="bizNo" className="input-light" maxLength={15} onChange={inputTelNumberCheck} />
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -196,44 +331,49 @@ export default function Join() {
|
|||||||
<col />
|
<col />
|
||||||
</colgroup>
|
</colgroup>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
{/* 담당자명 */}
|
||||||
<tr>
|
<tr>
|
||||||
<th>
|
<th>
|
||||||
{getMessage('join.sub2.userNm')} <span className="important">*</span>
|
{getMessage('join.sub2.userNm')} <span className="important">*</span>
|
||||||
</th>
|
</th>
|
||||||
<td>
|
<td>
|
||||||
<div className="input-wrap" style={{ width: '200px' }}>
|
<div className="input-wrap" style={{ width: '200px' }}>
|
||||||
<input type="text" id="userNm" name="userNm" className="input-light" required />
|
<input type="text" id="userNm" name="userNm" className="input-light" maxLength={20} ref={userNmRef} />
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
{/* 담당자명 후리가나 */}
|
||||||
<tr>
|
<tr>
|
||||||
<th>{getMessage('join.sub2.userNmKana')}</th>
|
<th>{getMessage('join.sub2.userNmKana')}</th>
|
||||||
<td>
|
<td>
|
||||||
<div className="input-wrap" style={{ width: '200px' }}>
|
<div className="input-wrap" style={{ width: '200px' }}>
|
||||||
<input type="text" id="userNmKana" name="userNmKana" className="input-light" />
|
<input type="text" id="userNmKana" name="userNmKana" maxLength={20} className="input-light" />
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
{/* 신청 ID */}
|
||||||
<tr>
|
<tr>
|
||||||
<th>
|
<th>
|
||||||
{getMessage('join.sub2.userId')} <span className="important">*</span>
|
{getMessage('join.sub2.userId')} <span className="important">*</span>
|
||||||
</th>
|
</th>
|
||||||
<td>
|
<td>
|
||||||
<div className="input-wrap" style={{ width: '200px' }}>
|
<div className="input-wrap" style={{ width: '200px' }}>
|
||||||
<input type="text" id="userId" name="userId" className="input-light" required />
|
<input type="text" id="userId" name="userId" className="input-light" maxLength={20} ref={userIdRef} />
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
{/* 이메일 주소 */}
|
||||||
<tr>
|
<tr>
|
||||||
<th>
|
<th>
|
||||||
{getMessage('join.sub2.email')} <span className="important">*</span>
|
{getMessage('join.sub2.email')} <span className="important">*</span>
|
||||||
</th>
|
</th>
|
||||||
<td>
|
<td>
|
||||||
<div className="input-wrap" style={{ width: '200px' }}>
|
<div className="input-wrap" style={{ width: '200px' }}>
|
||||||
<input type="text" id="email" name="email" className="input-light" required />
|
<input type="text" id="email" name="email" className="input-light" maxLength={30} ref={emailRef} />
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
{/* 전화번호 */}
|
||||||
<tr>
|
<tr>
|
||||||
<th>
|
<th>
|
||||||
{getMessage('join.sub2.telNo')} <span className="important">*</span>
|
{getMessage('join.sub2.telNo')} <span className="important">*</span>
|
||||||
@ -246,11 +386,14 @@ export default function Join() {
|
|||||||
name="userTelNo"
|
name="userTelNo"
|
||||||
className="input-light"
|
className="input-light"
|
||||||
placeholder={getMessage('join.sub2.telNo_placeholder')}
|
placeholder={getMessage('join.sub2.telNo_placeholder')}
|
||||||
required
|
maxLength={15}
|
||||||
|
onChange={inputTelNumberCheck}
|
||||||
|
ref={userTelNoRef}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
{/* FAX 번호 */}
|
||||||
<tr>
|
<tr>
|
||||||
<th>
|
<th>
|
||||||
{getMessage('join.sub2.fax')} <span className="important">*</span>
|
{getMessage('join.sub2.fax')} <span className="important">*</span>
|
||||||
@ -263,16 +406,19 @@ export default function Join() {
|
|||||||
name="userFax"
|
name="userFax"
|
||||||
className="input-light"
|
className="input-light"
|
||||||
placeholder={getMessage('join.sub1.fax_placeholder')}
|
placeholder={getMessage('join.sub1.fax_placeholder')}
|
||||||
required
|
maxLength={15}
|
||||||
|
onChange={inputTelNumberCheck}
|
||||||
|
ref={userFaxRef}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
{/* 부서명 */}
|
||||||
<tr>
|
<tr>
|
||||||
<th>{getMessage('join.sub2.category')}</th>
|
<th>{getMessage('join.sub2.category')}</th>
|
||||||
<td>
|
<td>
|
||||||
<div className="input-wrap" style={{ width: '200px' }}>
|
<div className="input-wrap" style={{ width: '200px' }}>
|
||||||
<input type="text" id="category" name="category" className="input-light" />
|
<input type="text" id="category" name="category" className="input-light" maxLength={20} />
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@ -98,6 +98,7 @@ export default function Login() {
|
|||||||
pwdInitYn: 'Y',
|
pwdInitYn: 'Y',
|
||||||
storeLvl: '1',
|
storeLvl: '1',
|
||||||
groupId: '60000',
|
groupId: '60000',
|
||||||
|
custCd: '100000',
|
||||||
})
|
})
|
||||||
setSessionState({
|
setSessionState({
|
||||||
userId: 'NEW016610',
|
userId: 'NEW016610',
|
||||||
@ -115,6 +116,7 @@ export default function Login() {
|
|||||||
pwdInitYn: 'Y',
|
pwdInitYn: 'Y',
|
||||||
storeLvl: '1',
|
storeLvl: '1',
|
||||||
groupId: '60000',
|
groupId: '60000',
|
||||||
|
custCd: '100000',
|
||||||
})
|
})
|
||||||
if (chkLoginId) {
|
if (chkLoginId) {
|
||||||
Cookies.set('chkLoginId', formData.get('id'), { expires: 7 })
|
Cookies.set('chkLoginId', formData.get('id'), { expires: 7 })
|
||||||
@ -331,7 +333,15 @@ export default function Login() {
|
|||||||
></button>
|
></button>
|
||||||
</div>
|
</div>
|
||||||
<div className="pwreset-btn-box">
|
<div className="pwreset-btn-box">
|
||||||
<button type="button" className="login-btn light mr5" onClick={() => setPasswordReset(1)}>
|
<button
|
||||||
|
type="button"
|
||||||
|
className="login-btn light mr5"
|
||||||
|
onClick={() => {
|
||||||
|
setPasswordReset(1)
|
||||||
|
setCheckEmail('')
|
||||||
|
setCheckId('')
|
||||||
|
}}
|
||||||
|
>
|
||||||
{getMessage('login.init_password.btn.back')}
|
{getMessage('login.init_password.btn.back')}
|
||||||
</button>
|
</button>
|
||||||
<button type="button" className="login-btn" onClick={initPasswordProcess}>
|
<button type="button" className="login-btn" onClick={initPasswordProcess}>
|
||||||
|
|||||||
@ -1,13 +1,13 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect } from 'react'
|
||||||
import '@/styles/contents.scss'
|
import '@/styles/contents.scss'
|
||||||
|
import { useRecoilState } from 'recoil'
|
||||||
|
import { contextMenuListState, contextMenuState } from '@/store/contextMenu'
|
||||||
|
|
||||||
export default function QContextMenu(props) {
|
export default function QContextMenu(props) {
|
||||||
const { contextRef, canvasProps } = props
|
const { contextRef, canvasProps, handleKeyup } = props
|
||||||
|
const [contextMenu, setContextMenu] = useRecoilState(contextMenuState)
|
||||||
// const children = useRecoilValue(modalContent)
|
const [contextMenuList, setContextMenuList] = useRecoilState(contextMenuListState)
|
||||||
const [contextMenu, setContextMenu] = useState({ visible: false, x: 0, y: 0 })
|
|
||||||
|
|
||||||
const activeObject = canvasProps?.getActiveObject() //액티브된 객체를 가져옴
|
const activeObject = canvasProps?.getActiveObject() //액티브된 객체를 가져옴
|
||||||
|
|
||||||
let contextType = ''
|
let contextType = ''
|
||||||
@ -21,13 +21,23 @@ export default function QContextMenu(props) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getYPosition = (e) => {
|
||||||
|
const contextLength = contextMenuList.reduce((acc, cur, index) => {
|
||||||
|
return acc + cur.length
|
||||||
|
}, 0)
|
||||||
|
return e?.clientY - (contextLength * 25 + contextMenuList.length * 2 * 17)
|
||||||
|
}
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!contextRef.current) return
|
if (!contextRef.current) return
|
||||||
|
|
||||||
const handleContextMenu = (e) => {
|
const handleContextMenu = (e) => {
|
||||||
// e.preventDefault() //기존 contextmenu 막고
|
// e.preventDefault() //기존 contextmenu 막고
|
||||||
setContextMenu({ visible: true, x: e.pageX, y: e.pageY })
|
const position = {
|
||||||
// console.log(111, canvasProps)
|
x: window.innerWidth / 2 < e.pageX ? e.pageX - 240 : e.pageX,
|
||||||
|
y: window.innerHeight / 2 < e.pageY ? getYPosition(e) : e.pageY,
|
||||||
|
}
|
||||||
|
setContextMenu({ visible: true, ...position })
|
||||||
|
document.addEventListener('keyup', (e) => handleKeyup(e))
|
||||||
canvasProps?.upperCanvasEl.removeEventListener('contextmenu', handleContextMenu) //한번 노출 후 이벤트 삭제
|
canvasProps?.upperCanvasEl.removeEventListener('contextmenu', handleContextMenu) //한번 노출 후 이벤트 삭제
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,13 +1,13 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
|
|
||||||
export default function QSelectBox({ title = '', options, onChange, value }) {
|
export default function QSelectBox({ title = '', options, onChange, value, disabled = false, params = {} }) {
|
||||||
const [openSelect, setOpenSelect] = useState(false)
|
const [openSelect, setOpenSelect] = useState(false)
|
||||||
const [selected, setSelected] = useState(title === '' ? options[0].name : title)
|
const [selected, setSelected] = useState(title === '' ? options[0].name : title)
|
||||||
|
|
||||||
const handleClickSelectOption = (option) => {
|
const handleClickSelectOption = (option) => {
|
||||||
setSelected(option.name)
|
setSelected(option.name)
|
||||||
onChange?.(option)
|
onChange?.(option, params)
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -15,7 +15,7 @@ export default function QSelectBox({ title = '', options, onChange, value }) {
|
|||||||
}, [value])
|
}, [value])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`sort-select ${openSelect ? 'active' : ''}`} onClick={() => setOpenSelect(!openSelect)}>
|
<div className={`sort-select ${openSelect ? 'active' : ''}`} onClick={disabled ? () => {} : () => setOpenSelect(!openSelect)}>
|
||||||
<p>{selected}</p>
|
<p>{selected}</p>
|
||||||
<ul className="select-item-wrap">
|
<ul className="select-item-wrap">
|
||||||
{options?.map((option) => (
|
{options?.map((option) => (
|
||||||
|
|||||||
@ -81,11 +81,11 @@ export default function Table({ clsCode }) {
|
|||||||
{/* 번호 */}
|
{/* 번호 */}
|
||||||
{board.rowNumber}
|
{board.rowNumber}
|
||||||
</td>
|
</td>
|
||||||
<td style={{ textAlign: 'center' }}>
|
<td>
|
||||||
{/* 제목 */}
|
{/* 제목 */}
|
||||||
<div className="text-frame">
|
<div className="text-frame">
|
||||||
<div className="text-overflow">{board.title}</div>
|
<div className="text-overflow">{board.title}</div>
|
||||||
{board.attachYn && <span className="clip"></span>}
|
{board.attachYn === 'Y' && <span className="clip"></span>}
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td className="al-c">
|
<td className="al-c">
|
||||||
|
|||||||
@ -3,8 +3,11 @@
|
|||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { useAxios } from '@/hooks/useAxios'
|
import { useAxios } from '@/hooks/useAxios'
|
||||||
import { handleFileDown } from '@/util/board-utils'
|
import { handleFileDown } from '@/util/board-utils'
|
||||||
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
|
|
||||||
export default function BoardDetailModal({ noticeNo, setOpen }) {
|
export default function BoardDetailModal({ noticeNo, setOpen }) {
|
||||||
|
const { getMessage } = useMessage()
|
||||||
|
|
||||||
// api 조회 관련
|
// api 조회 관련
|
||||||
const { get } = useAxios()
|
const { get } = useAxios()
|
||||||
const [boardDetail, setBoardDetail] = useState({})
|
const [boardDetail, setBoardDetail] = useState({})
|
||||||
@ -46,7 +49,7 @@ export default function BoardDetailModal({ noticeNo, setOpen }) {
|
|||||||
setOpen(false)
|
setOpen(false)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
닫기
|
{getMessage('board.sub.btn.close')}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="modal-body">
|
<div className="modal-body">
|
||||||
@ -55,7 +58,7 @@ export default function BoardDetailModal({ noticeNo, setOpen }) {
|
|||||||
|
|
||||||
{boardDetail.listFile && (
|
{boardDetail.listFile && (
|
||||||
<dl className="community_detail-file-wrap">
|
<dl className="community_detail-file-wrap">
|
||||||
<dt>첨부파일 목록</dt>
|
<dt>{getMessage('board.sub.fileList')}</dt>
|
||||||
{boardDetail.listFile.map((boardFile) => (
|
{boardDetail.listFile.map((boardFile) => (
|
||||||
<dd key={boardFile.encodeFileNo}>
|
<dd key={boardFile.encodeFileNo}>
|
||||||
<button type="button" className="down" onClick={() => handleFileDown(boardFile)}>
|
<button type="button" className="down" onClick={() => handleFileDown(boardFile)}>
|
||||||
|
|||||||
354
src/components/estimate/Estimate.jsx
Normal file
@ -0,0 +1,354 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import { useEffect, useState, useRef } from 'react'
|
||||||
|
import { useRecoilValue } from 'recoil'
|
||||||
|
import { floorPlanObjectState } from '@/store/floorPlanObjectAtom'
|
||||||
|
import { sessionStore } from '@/store/commonAtom'
|
||||||
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
|
import { useCanvasMenu } from '@/hooks/common/useCanvasMenu'
|
||||||
|
import SingleDatePicker from '../common/datepicker/SingleDatePicker'
|
||||||
|
import EstimateFileUploader from './EstimateFileUploader'
|
||||||
|
|
||||||
|
export default function Estimate({ params }) {
|
||||||
|
const [objectNo, setObjectNo] = useState('')
|
||||||
|
const [files, setFiles] = useState([]) //첨부파일
|
||||||
|
|
||||||
|
const sessionState = useRecoilValue(sessionStore)
|
||||||
|
const objectRecoil = useRecoilValue(floorPlanObjectState)
|
||||||
|
const { getMessage } = useMessage()
|
||||||
|
|
||||||
|
const { setMenuNumber } = useCanvasMenu()
|
||||||
|
|
||||||
|
const fileUploadProps = {
|
||||||
|
// objectNo: '',
|
||||||
|
// planNo: params.pid,
|
||||||
|
// category: '10',
|
||||||
|
uploadFiles: files,
|
||||||
|
setUploadFiles: setFiles,
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setObjectNo(objectRecoil.floorPlanObjectNo)
|
||||||
|
}, [objectRecoil])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (objectNo) {
|
||||||
|
//Q101X278191023001
|
||||||
|
console.log('세션정보::::', sessionState)
|
||||||
|
//상세API호출
|
||||||
|
}
|
||||||
|
}, [objectNo])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setMenuNumber(5)
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="sub-content estimate">
|
||||||
|
<div className="sub-content-inner">
|
||||||
|
{/* 물건번호, 견적서번호, 등록일, 변경일시 시작 */}
|
||||||
|
<div className="sub-content-box">
|
||||||
|
<div className="sub-table-box">
|
||||||
|
<div className="estimate-list-wrap one">
|
||||||
|
<div className="estimate-box">
|
||||||
|
<div className="estimate-tit">{getMessage('estimate.detail.objectNo')}</div>
|
||||||
|
<div className="estimate-name">
|
||||||
|
{objectNo} (Plan No: {params.pid})
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="estimate-box">
|
||||||
|
<div className="estimate-tit">{getMessage('estimate.detail.estimateNo')}</div>
|
||||||
|
<div className="estimate-name">5242310200065242</div>
|
||||||
|
</div>
|
||||||
|
<div className="estimate-box">
|
||||||
|
<div className="estimate-tit">{getMessage('estimate.detail.createDatetime')}</div>
|
||||||
|
<div className="estimate-name">9999.09.28</div>
|
||||||
|
</div>
|
||||||
|
<div className="estimate-box">
|
||||||
|
<div className="estimate-tit">{getMessage('estimate.detail.lastEditDatetime')}</div>
|
||||||
|
<div className="estimate-name">9999.09.28 06:36</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/* 물건번호, 견적서번호, 등록일, 변경일시 끝 */}
|
||||||
|
{/* 기본정보 시작 */}
|
||||||
|
<div className="sub-content-box">
|
||||||
|
<div className="sub-table-box">
|
||||||
|
<div className="table-box-title-wrap">
|
||||||
|
<div className="title-wrap">
|
||||||
|
<h3>{getMessage('estimate.detail.header.title')}</h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="common-table bt-able">
|
||||||
|
<table>
|
||||||
|
<colgroup>
|
||||||
|
<col style={{ width: '160px' }} />
|
||||||
|
<col />
|
||||||
|
<col style={{ width: '160px' }} />
|
||||||
|
<col />
|
||||||
|
</colgroup>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
{/* 1차 판매점명 */}
|
||||||
|
<th>{getMessage('estimate.detail.saleStoreId')}</th>
|
||||||
|
<td></td>
|
||||||
|
{/* 견적일 */}
|
||||||
|
<th>
|
||||||
|
{getMessage('estimate.detail.estimateDate')} <span className="important">*</span>
|
||||||
|
</th>
|
||||||
|
<td>
|
||||||
|
<div className="date-picker" style={{ width: '350px' }}>
|
||||||
|
<SingleDatePicker />
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
{/* 2차 판매점명 */}
|
||||||
|
<th>{getMessage('estimate.detail.otherSaleStoreId')}</th>
|
||||||
|
<td></td>
|
||||||
|
{/* 담당자 */}
|
||||||
|
<th>
|
||||||
|
{getMessage('estimate.detail.receiveUser')} <span className="important">*</span>
|
||||||
|
</th>
|
||||||
|
<td>
|
||||||
|
<div className="input-wrap" style={{ width: '350px' }}>
|
||||||
|
<input type="text" className="input-light" defaultValue={'물건정보에서 입력한 담당자명 표시'} />
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
{/* 안건명 */}
|
||||||
|
<th>
|
||||||
|
{getMessage('estimate.detail.title')} <span className="important">*</span>
|
||||||
|
</th>
|
||||||
|
<td colSpan={3}>
|
||||||
|
<div className="form-flex-wrap">
|
||||||
|
<div className="input-wrap mr5" style={{ width: '610px' }}>
|
||||||
|
<input type="text" className="input-light" defaultValue={'안건명:::'} />
|
||||||
|
</div>
|
||||||
|
<div className="input-wrap" style={{ width: '200px' }}>
|
||||||
|
<input type="text" className="input-light" defaultValue={'경칭?'} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
{/* 메모 */}
|
||||||
|
<th>{getMessage('estimate.detail.remarks')}</th>
|
||||||
|
<td colSpan={3}>물건정보에서 입력한 메모 표시</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
{/* 주문분류 */}
|
||||||
|
<th>
|
||||||
|
{getMessage('estimate.detail.orderType')} <span className="important">*</span>
|
||||||
|
</th>
|
||||||
|
<td colSpan={3}>
|
||||||
|
<div className="radio-wrap"></div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
{/* 지붕재・사양시공 최대4개*/}
|
||||||
|
<th>{getMessage('estimate.detail.roofCns')}</th>
|
||||||
|
<td colSpan={3}>
|
||||||
|
<div className="form-flex-wrap mb5">
|
||||||
|
<div className="input-wrap mr5" style={{ width: '610px' }}>
|
||||||
|
<input type="text" className="input-light" defaultValue={'ハゼ式折板(角ハゼ)'} readOnly />
|
||||||
|
</div>
|
||||||
|
<div className="input-wrap" style={{ width: '200px' }}>
|
||||||
|
<input type="text" className="input-light" defaultValue={'標準施工'} readOnly />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="form-flex-wrap mb5"></div>
|
||||||
|
<div className="form-flex-wrap mb5"></div>
|
||||||
|
{/* 마지막div엔 mb5 제외 */}
|
||||||
|
<div className="form-flex-wrap"></div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
{/* 비고 */}
|
||||||
|
<th>{getMessage('estimate.detail.note')}</th>
|
||||||
|
<td colSpan={3}>
|
||||||
|
<div className="input-wrap">
|
||||||
|
<input type="text" className="input-light" />
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{/* 파일첨부 시작 */}
|
||||||
|
<div className="table-box-title-wrap">
|
||||||
|
<div className="title-wrap">
|
||||||
|
<h3>{getMessage('estimate.detail.header.fileList1')}</h3>
|
||||||
|
<div className="d-check-box light mr5">
|
||||||
|
<input type="checkbox" id="next" />
|
||||||
|
<label htmlFor="next" style={{ color: '#101010' }}>
|
||||||
|
{getMessage('estimate.detail.nextSubmit')}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="common-table mb10">
|
||||||
|
<table>
|
||||||
|
<colgroup>
|
||||||
|
<col style={{ width: '160px' }} />
|
||||||
|
<col />
|
||||||
|
</colgroup>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th>{getMessage('estimate.detail.header.fileList1')}</th>
|
||||||
|
<td>
|
||||||
|
<EstimateFileUploader {...fileUploadProps} />
|
||||||
|
{/* <div className="drag-file-box">
|
||||||
|
<div className="btn-area">
|
||||||
|
<Button type="button" className="btn-origin grey" onClick={handleButtonClick}>
|
||||||
|
{getMessage('estimate.detail.fileList.btn')}
|
||||||
|
</Button>
|
||||||
|
<input
|
||||||
|
type="file"
|
||||||
|
id="fileUpload"
|
||||||
|
name="fileUpload"
|
||||||
|
ref={fileInputRef}
|
||||||
|
onChange={onChangeFiles}
|
||||||
|
style={{ display: 'none' }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="drag-file-area">
|
||||||
|
<p>Drag file here</p>
|
||||||
|
<ul className="file-list"></ul>
|
||||||
|
</div>
|
||||||
|
</div> */}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{/* 첨부파일 목록 시작 */}
|
||||||
|
<div className="common-table bt-able">
|
||||||
|
<table>
|
||||||
|
<colgroup>
|
||||||
|
<col style={{ width: '160px' }} />
|
||||||
|
<col />
|
||||||
|
</colgroup>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th>{getMessage('estimate.detail.header.fileList2')}</th>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{/* 첨부파일 목록 끝 */}
|
||||||
|
{/* 파일첨부 끝 */}
|
||||||
|
{/* 견적특이사항 시작 */}
|
||||||
|
<div className="table-box-title-wrap">
|
||||||
|
<div className="title-wrap">
|
||||||
|
<h3 className="product">{getMessage('estimate.detail.header.specialEstimate')}</h3>
|
||||||
|
<div className="product_tit">{getMessage('estimate.detail.header.specialEstimateProductInfo')}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/* 공통코드영역시작 */}
|
||||||
|
<div className="special-note-check-wrap"></div>
|
||||||
|
{/* 공통코드영역끝 */}
|
||||||
|
{/* 견적특이사항 내용영역시작 */}
|
||||||
|
<div className="calculation-estimate"></div>
|
||||||
|
{/* 견적특이사항 내용영역끝 */}
|
||||||
|
{/* 견적특이사항 끝 */}
|
||||||
|
{/* 제품정보 시작 */}
|
||||||
|
<div className="table-box-title-wrap">
|
||||||
|
<div className="title-wrap">
|
||||||
|
<h3>{getMessage('estimate.detail.header.specialEstimateProductInfo')}</h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="estimate-wrap">
|
||||||
|
<div className="estimate-list-wrap one">
|
||||||
|
<div className="estimate-box">
|
||||||
|
<div className="estimate-tit">{getMessage('estimate.detail.sepcialEstimateProductInfo.totPcs')}</div>
|
||||||
|
<div className="estimate-name blue">74</div>
|
||||||
|
</div>
|
||||||
|
<div className="estimate-box">
|
||||||
|
<div className="estimate-tit">{getMessage('estimate.detail.sepcialEstimateProductInfo.vol')}</div>
|
||||||
|
<div className="estimate-name blue">8300</div>
|
||||||
|
</div>
|
||||||
|
<div className="estimate-box">
|
||||||
|
<div className="estimate-tit">{getMessage('estimate.detail.sepcialEstimateProductInfo.netAmt')}</div>
|
||||||
|
<div className="estimate-name blue">6,798,900</div>
|
||||||
|
</div>
|
||||||
|
<div className="estimate-box">
|
||||||
|
<div className="estimate-tit">{getMessage('estimate.detail.sepcialEstimateProductInfo.vat')}</div>
|
||||||
|
<div className="estimate-name blue">679,890</div>
|
||||||
|
</div>
|
||||||
|
<div className="estimate-box">
|
||||||
|
<div className="estimate-tit">{getMessage('estimate.detail.sepcialEstimateProductInfo.totPrice')}</div>
|
||||||
|
<div className="estimate-name red">7,478,790</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/* YJOD면 아래영역 숨김 */}
|
||||||
|
<div className="common-table bt-able">
|
||||||
|
<table>
|
||||||
|
<colgroup>
|
||||||
|
<col style={{ width: '160px' }} />
|
||||||
|
<col />
|
||||||
|
<col style={{ width: '160px' }} />
|
||||||
|
<col />
|
||||||
|
<col style={{ width: '160px' }} />
|
||||||
|
<col />
|
||||||
|
</colgroup>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
{getMessage('estimate.detail.sepcialEstimateProductInfo.pkgUnitPrice')}
|
||||||
|
<span className="important">*</span>
|
||||||
|
</th>
|
||||||
|
<td>
|
||||||
|
<div className="input-wrap">
|
||||||
|
<input type="text" className="input-light" />
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<th>{getMessage('estimate.detail.sepcialEstimateProductInfo.pkgWeight')}</th>
|
||||||
|
<td>{getMessage('estimate.detail.sepcialEstimateProductInfo.calcFormula1')}</td>
|
||||||
|
<th>{getMessage('estimate.detail.sepcialEstimateProductInfo.pkgPrice')}</th>
|
||||||
|
<td>{getMessage('estimate.detail.sepcialEstimateProductInfo.calcFormula2')}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{/* 제품정보 끝 */}
|
||||||
|
{/* 가격표시영역시작 */}
|
||||||
|
<div className="estimate-product-option">
|
||||||
|
<div className="product-price-wrap">
|
||||||
|
<div className="product-price-tit">{getMessage('estimate.detail.header.showPrice')}</div>
|
||||||
|
<div className="select-wrap"></div>
|
||||||
|
<button className="btn-origin grey ml5">{getMessage('estimate.detail.showPrice.btn1')}</button>
|
||||||
|
</div>
|
||||||
|
<div className="product-edit-wrap">
|
||||||
|
<div className="product-edit-explane">
|
||||||
|
<div className="click-check">
|
||||||
|
<span className="ico"></span>
|
||||||
|
{getMessage('estimate.detail.showPrice.description')}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="product-edit-btn">
|
||||||
|
<button className="btn-origin navy mr5">
|
||||||
|
<span className="plus"></span>
|
||||||
|
{getMessage('estimate.detail.showPrice.btn2')}
|
||||||
|
</button>
|
||||||
|
<button className="btn-origin grey">
|
||||||
|
<span className="minus"></span>
|
||||||
|
{getMessage('estimate.detail.showPrice.btn3')}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/* 가격표시영역끝 */}
|
||||||
|
{/* html테이블시작 */}
|
||||||
|
<div className="q-grid no-cols"></div>
|
||||||
|
{/* html테이블끝 */}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/* 기본정보끝 */}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
91
src/components/estimate/EstimateFileUploader.jsx
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import { useContext, useRef } from 'react'
|
||||||
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
|
import { SessionContext } from '@/app/SessionProvider'
|
||||||
|
|
||||||
|
export default function EstimateFileUploader({ uploadFiles, setUploadFiles }) {
|
||||||
|
const fileInputRef = useRef(null)
|
||||||
|
const { getMessage } = useMessage()
|
||||||
|
const { session } = useContext(SessionContext)
|
||||||
|
|
||||||
|
const handleButtonClick = (e) => {
|
||||||
|
e.preventDefault()
|
||||||
|
fileInputRef.current.click()
|
||||||
|
}
|
||||||
|
|
||||||
|
const onChangeFiles = async (e) => {
|
||||||
|
// const formData = new FormData()
|
||||||
|
// formData.append('file', e.target.files[0])
|
||||||
|
// formData.append('objectNo', objectNo) // 받아와야 하는 값
|
||||||
|
// formData.append('planNo', planNo) // 받아와야 하는 값
|
||||||
|
// formData.append('category', category) // 받아와야 하는 값
|
||||||
|
// formData.append('userId', session.userId)
|
||||||
|
|
||||||
|
// await promisePost({ url: '/api/file/fileUpload', data: formData }).then((res) => {
|
||||||
|
// if (res.data > 0) setUploadFiles([...files, { name: e.target.files[0].name, id: uuidv4() }])
|
||||||
|
// })
|
||||||
|
setUploadFiles([...uploadFiles, { data: e.target.files[0], id: uuidv4() }])
|
||||||
|
}
|
||||||
|
|
||||||
|
const deleteFile = (id) => {
|
||||||
|
setUploadFiles(uploadFiles.filter((file) => file.id !== id))
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleDrop = (e) => {
|
||||||
|
e.preventDefault()
|
||||||
|
e.stopPropagation()
|
||||||
|
const fileList = []
|
||||||
|
Array.from(e.dataTransfer.files).forEach((file) => {
|
||||||
|
fileList.push({ data: file, id: uuidv4() })
|
||||||
|
})
|
||||||
|
setUploadFiles([...uploadFiles, ...fileList])
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleDragOver = (e) => {
|
||||||
|
e.preventDefault()
|
||||||
|
e.stopPropagation()
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleDragEnd = (e) => {
|
||||||
|
e.preventDefault()
|
||||||
|
e.stopPropagation()
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleDragLeave = (e) => {
|
||||||
|
e.preventDefault()
|
||||||
|
e.stopPropagation()
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="drag-file-box">
|
||||||
|
<div className="btn-area">
|
||||||
|
<label className="file-upload" htmlFor="img" onClick={handleButtonClick}>
|
||||||
|
{getMessage('estimate.detail.fileList.btn')}
|
||||||
|
</label>
|
||||||
|
<input type="file" name="file" id="img" ref={fileInputRef} style={{ display: 'none' }} onChange={(e) => onChangeFiles(e)} />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className="drag-file-area"
|
||||||
|
draggable
|
||||||
|
onDrop={(e) => handleDrop(e)}
|
||||||
|
onDragOver={(e) => handleDragOver(e)}
|
||||||
|
onDragEnd={(e) => handleDragEnd(e)}
|
||||||
|
onDragLeave={(e) => handleDragLeave(e)}
|
||||||
|
>
|
||||||
|
<p>Drag file here</p>
|
||||||
|
<ul className="file-list">
|
||||||
|
{uploadFiles.length > 0 &&
|
||||||
|
uploadFiles.map((file) => (
|
||||||
|
<li className="file-item" key={file.id}>
|
||||||
|
<span>
|
||||||
|
{file.data.name} <button className="delete" onClick={() => deleteFile(file.id)}></button>
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -12,7 +12,7 @@ export const QLine = fabric.util.createClass(fabric.Line, {
|
|||||||
idx: 0,
|
idx: 0,
|
||||||
area: 0,
|
area: 0,
|
||||||
children: [],
|
children: [],
|
||||||
initialize: function (points, options, canvas) {
|
initialize: function (points, options, length = 0) {
|
||||||
this.callSuper('initialize', points, { ...options, selectable: options.selectable ?? true })
|
this.callSuper('initialize', points, { ...options, selectable: options.selectable ?? true })
|
||||||
if (options.id) {
|
if (options.id) {
|
||||||
this.id = options.id
|
this.id = options.id
|
||||||
@ -21,13 +21,15 @@ export const QLine = fabric.util.createClass(fabric.Line, {
|
|||||||
}
|
}
|
||||||
this.line = this
|
this.line = this
|
||||||
// 소수점 전부 제거
|
// 소수점 전부 제거
|
||||||
points.forEach((point) => {
|
points = points.map((point) => Math.round(point))
|
||||||
point = Math.round(point)
|
|
||||||
})
|
|
||||||
|
|
||||||
this.idx = options.idx ?? 0
|
this.idx = options.idx ?? 0
|
||||||
this.direction = options.direction ?? getDirectionByPoint({ x: this.x1, y: this.y1 }, { x: this.x2, y: this.y2 })
|
this.direction = options.direction ?? getDirectionByPoint({ x: this.x1, y: this.y1 }, { x: this.x2, y: this.y2 })
|
||||||
|
if (length !== 0) {
|
||||||
|
this.length = length
|
||||||
|
} else {
|
||||||
this.setLength()
|
this.setLength()
|
||||||
|
}
|
||||||
|
|
||||||
this.startPoint = { x: this.x1, y: this.y1 }
|
this.startPoint = { x: this.x1, y: this.y1 }
|
||||||
this.endPoint = { x: this.x2, y: this.y2 }
|
this.endPoint = { x: this.x2, y: this.y2 }
|
||||||
@ -37,12 +39,6 @@ export const QLine = fabric.util.createClass(fabric.Line, {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
toObject: function (propertiesToInclude) {
|
|
||||||
return fabric.util.object.extend(this.callSuper('toObject', propertiesToInclude), {
|
|
||||||
type: this.type,
|
|
||||||
text: this.text,
|
|
||||||
})
|
|
||||||
},
|
|
||||||
init: function () {
|
init: function () {
|
||||||
this.addLengthText()
|
this.addLengthText()
|
||||||
|
|
||||||
@ -148,7 +144,7 @@ export const QLine = fabric.util.createClass(fabric.Line, {
|
|||||||
|
|
||||||
getLength() {
|
getLength() {
|
||||||
//10배 곱해진 값 return
|
//10배 곱해진 값 return
|
||||||
return Number(this.length.toFixed(0) * 10)
|
return Number(this.length.toFixed(1)) * 10
|
||||||
},
|
},
|
||||||
|
|
||||||
setViewLengthText(bool) {
|
setViewLengthText(bool) {
|
||||||
|
|||||||
@ -34,8 +34,8 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
|
|||||||
|
|
||||||
// 소수점 전부 제거
|
// 소수점 전부 제거
|
||||||
points.forEach((point) => {
|
points.forEach((point) => {
|
||||||
point.x = Math.round(point.x)
|
point.x = Number(point.x.toFixed(1))
|
||||||
point.y = Math.round(point.y)
|
point.y = Number(point.y.toFixed(1))
|
||||||
})
|
})
|
||||||
options.selectable = options.selectable ?? true
|
options.selectable = options.selectable ?? true
|
||||||
options.sort = options.sort ?? true
|
options.sort = options.sort ?? true
|
||||||
@ -111,17 +111,6 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
|
|||||||
|
|
||||||
this.shape = shape
|
this.shape = shape
|
||||||
},
|
},
|
||||||
|
|
||||||
toObject: function (propertiesToInclude) {
|
|
||||||
return fabric.util.object.extend(this.callSuper('toObject', propertiesToInclude), {
|
|
||||||
id: this.id,
|
|
||||||
type: this.type,
|
|
||||||
text: this.text,
|
|
||||||
hips: this.hips,
|
|
||||||
ridges: this.ridges,
|
|
||||||
connectRidges: this.connectRidges,
|
|
||||||
})
|
|
||||||
},
|
|
||||||
init: function () {
|
init: function () {
|
||||||
this.addLengthText()
|
this.addLengthText()
|
||||||
|
|
||||||
@ -215,7 +204,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
|
|||||||
addLengthText() {
|
addLengthText() {
|
||||||
this.canvas
|
this.canvas
|
||||||
?.getObjects()
|
?.getObjects()
|
||||||
.filter((obj) => obj.name === 'lengthText' && obj.parent === this)
|
.filter((obj) => obj.name === 'lengthText' && obj.parentId === this.id)
|
||||||
.forEach((text) => {
|
.forEach((text) => {
|
||||||
this.canvas.remove(text)
|
this.canvas.remove(text)
|
||||||
})
|
})
|
||||||
@ -226,7 +215,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
|
|||||||
const end = points[(i + 1) % points.length]
|
const end = points[(i + 1) % points.length]
|
||||||
const dx = end.x - start.x
|
const dx = end.x - start.x
|
||||||
const dy = end.y - start.y
|
const dy = end.y - start.y
|
||||||
const length = Number(Math.sqrt(dx * dx + dy * dy).toFixed(0)) * 10
|
const length = Number(Math.sqrt(dx * dx + dy * dy).toFixed(1)) * 10
|
||||||
|
|
||||||
let midPoint
|
let midPoint
|
||||||
|
|
||||||
|
|||||||
@ -2,72 +2,77 @@
|
|||||||
|
|
||||||
import { useEffect, useRef } from 'react'
|
import { useEffect, useRef } from 'react'
|
||||||
|
|
||||||
|
import { useRecoilValue } from 'recoil'
|
||||||
|
|
||||||
import { useCanvas } from '@/hooks/useCanvas'
|
import { useCanvas } from '@/hooks/useCanvas'
|
||||||
import { useEvent } from '@/hooks/useEvent'
|
import { useEvent } from '@/hooks/useEvent'
|
||||||
import { usePlan } from '@/hooks/usePlan'
|
import { usePlan } from '@/hooks/usePlan'
|
||||||
import { useContextMenu } from '@/hooks/useContextMenu'
|
import { useContextMenu } from '@/hooks/useContextMenu'
|
||||||
import { useRecoilValue } from 'recoil'
|
import { currentMenuState } from '@/store/canvasAtom'
|
||||||
import { currentObjectState } from '@/store/canvasAtom'
|
|
||||||
import { useCanvasEvent } from '@/hooks/useCanvasEvent'
|
|
||||||
import QContextMenu from '@/components/common/context-menu/QContextMenu'
|
import QContextMenu from '@/components/common/context-menu/QContextMenu'
|
||||||
import { useCanvasConfigInitialize } from '@/hooks/common/useCanvasConfigInitialize'
|
import { useCanvasConfigInitialize } from '@/hooks/common/useCanvasConfigInitialize'
|
||||||
|
import { MENU } from '@/common/common'
|
||||||
|
import PanelBatchStatistics from '@/components/floor-plan/modal/panelBatch/PanelBatchStatistics'
|
||||||
|
|
||||||
export default function CanvasFrame({ plan }) {
|
export default function CanvasFrame() {
|
||||||
const canvasRef = useRef(null)
|
const canvasRef = useRef(null)
|
||||||
const { canvas } = useCanvas('canvas')
|
const { canvas } = useCanvas('canvas')
|
||||||
const { handleZoomClear } = useCanvasEvent()
|
const { canvasLoadInit, gridInit } = useCanvasConfigInitialize()
|
||||||
const { contextMenu, currentContextMenu, setCurrentContextMenu, handleClick } = useContextMenu({
|
const currentMenu = useRecoilValue(currentMenuState)
|
||||||
externalFn: {
|
const { contextMenu, handleClick, handleKeyup } = useContextMenu()
|
||||||
handleZoomClear,
|
const { selectedPlan, modifiedPlanFlag, checkCanvasObjectEvent, resetModifiedPlans } = usePlan()
|
||||||
},
|
|
||||||
})
|
|
||||||
const { checkCanvasObjectEvent, checkUnsavedCanvasPlan } = usePlan()
|
|
||||||
const { canvasLoadInit } = useCanvasConfigInitialize()
|
|
||||||
const currentObject = useRecoilValue(currentObjectState)
|
|
||||||
|
|
||||||
useEvent()
|
useEvent()
|
||||||
|
|
||||||
const loadCanvas = () => {
|
const loadCanvas = () => {
|
||||||
if (canvas) {
|
if (canvas) {
|
||||||
canvas?.clear() // 캔버스를 초기화합니다.
|
canvas?.clear() // 캔버스를 초기화합니다.
|
||||||
if (plan?.canvasStatus) {
|
if (selectedPlan?.canvasStatus) {
|
||||||
canvas?.loadFromJSON(JSON.parse(plan.canvasStatus), function () {
|
canvas?.loadFromJSON(JSON.parse(selectedPlan.canvasStatus), function () {
|
||||||
canvas?.renderAll() // 캔버스를 다시 그립니다.
|
|
||||||
canvasLoadInit() //config된 상태로 캔버스 객체를 그린다
|
canvasLoadInit() //config된 상태로 캔버스 객체를 그린다
|
||||||
|
canvas?.renderAll() // 캔버스를 다시 그립니다.
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
gridInit()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
loadCanvas()
|
if (modifiedPlanFlag && selectedPlan?.id) {
|
||||||
}, [plan, canvas])
|
checkCanvasObjectEvent(selectedPlan.id)
|
||||||
|
}
|
||||||
|
}, [modifiedPlanFlag])
|
||||||
|
|
||||||
const onClickContextMenu = (index) => {}
|
useEffect(() => {
|
||||||
|
return () => {
|
||||||
|
resetModifiedPlans()
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
loadCanvas()
|
||||||
|
resetModifiedPlans()
|
||||||
|
}, [selectedPlan, canvas])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="canvas-frame">
|
<div className="canvas-frame">
|
||||||
<canvas ref={canvasRef} id="canvas" style={{ position: 'relative' }}></canvas>
|
<canvas ref={canvasRef} id="canvas" style={{ position: 'relative' }}></canvas>
|
||||||
|
|
||||||
<QContextMenu contextRef={canvasRef} canvasProps={canvas}>
|
<QContextMenu contextRef={canvasRef} canvasProps={canvas} handleKeyup={handleKeyup}>
|
||||||
{contextMenu.map((menus, index) => (
|
{contextMenu?.map((menus, index) => (
|
||||||
<ul key={index}>
|
<ul key={index}>
|
||||||
{menus.map((menu) => (
|
{menus.map((menu) => (
|
||||||
<li
|
<li key={menu.id} onClick={(e) => handleClick(e, menu)}>
|
||||||
key={menu.id}
|
|
||||||
onClick={(e) => {
|
|
||||||
if (menu.fn) {
|
|
||||||
menu.fn()
|
|
||||||
}
|
|
||||||
handleClick(e, menu)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{menu.name}
|
{menu.name}
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
))}
|
))}
|
||||||
</QContextMenu>
|
</QContextMenu>
|
||||||
|
{[
|
||||||
|
MENU.MODULE_CIRCUIT_SETTING.BASIC_SETTING,
|
||||||
|
MENU.MODULE_CIRCUIT_SETTING.CIRCUIT_TRESTLE_SETTING,
|
||||||
|
MENU.MODULE_CIRCUIT_SETTING.PLAN_ORIENTATION,
|
||||||
|
].includes(currentMenu) && <PanelBatchStatistics />}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,9 +8,11 @@ import { useSwal } from '@/hooks/useSwal'
|
|||||||
import { usePlan } from '@/hooks/usePlan'
|
import { usePlan } from '@/hooks/usePlan'
|
||||||
import { globalLocaleStore } from '@/store/localeAtom'
|
import { globalLocaleStore } from '@/store/localeAtom'
|
||||||
import { SessionContext } from '@/app/SessionProvider'
|
import { SessionContext } from '@/app/SessionProvider'
|
||||||
|
import { useCanvasMenu } from '@/hooks/common/useCanvasMenu'
|
||||||
|
|
||||||
export default function CanvasLayout(props) {
|
export default function CanvasLayout({ children }) {
|
||||||
const { menuNumber } = props
|
// const { menuNumber } = props
|
||||||
|
const { menuNumber } = useCanvasMenu()
|
||||||
const { session } = useContext(SessionContext)
|
const { session } = useContext(SessionContext)
|
||||||
const [objectNo, setObjectNo] = useState('test123240822001') // 이후 삭제 필요
|
const [objectNo, setObjectNo] = useState('test123240822001') // 이후 삭제 필요
|
||||||
const globalLocaleState = useRecoilValue(globalLocaleStore)
|
const globalLocaleState = useRecoilValue(globalLocaleStore)
|
||||||
@ -58,7 +60,7 @@ export default function CanvasLayout(props) {
|
|||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<CanvasFrame plan={plans.find((plan) => plan.isCurrent === true)} />
|
{children}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import { useEffect, useState } from 'react'
|
|||||||
|
|
||||||
import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'
|
import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'
|
||||||
|
|
||||||
|
import { usePathname, useRouter } from 'next/navigation'
|
||||||
import MenuDepth01 from './MenuDepth01'
|
import MenuDepth01 from './MenuDepth01'
|
||||||
import QSelectBox from '@/components/common/select/QSelectBox'
|
import QSelectBox from '@/components/common/select/QSelectBox'
|
||||||
import { v4 as uuidv4 } from 'uuid'
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
@ -11,70 +12,52 @@ import { useMessage } from '@/hooks/useMessage'
|
|||||||
import { usePlan } from '@/hooks/usePlan'
|
import { usePlan } from '@/hooks/usePlan'
|
||||||
import { useSwal } from '@/hooks/useSwal'
|
import { useSwal } from '@/hooks/useSwal'
|
||||||
import { useEvent } from '@/hooks/useEvent'
|
import { useEvent } from '@/hooks/useEvent'
|
||||||
import { canvasState, canvasZoomState, currentCanvasPlanState, currentMenuState, verticalHorizontalModeState } from '@/store/canvasAtom'
|
import { canvasSettingState, canvasState, canvasZoomState, currentMenuState, verticalHorizontalModeState } from '@/store/canvasAtom'
|
||||||
import { sessionStore } from '@/store/commonAtom'
|
import { sessionStore } from '@/store/commonAtom'
|
||||||
import { outerLinePointsState } from '@/store/outerLineAtom'
|
import { outerLinePointsState } from '@/store/outerLineAtom'
|
||||||
import { appMessageStore, globalLocaleStore } from '@/store/localeAtom'
|
import { appMessageStore, globalLocaleStore } from '@/store/localeAtom'
|
||||||
import { settingModalFirstOptionsState, wordDisplaySelector } from '@/store/settingAtom'
|
import { settingModalFirstOptionsState } from '@/store/settingAtom'
|
||||||
import { MENU } from '@/common/common'
|
|
||||||
|
|
||||||
import KO from '@/locales/ko.json'
|
import KO from '@/locales/ko.json'
|
||||||
import JA from '@/locales/ja.json'
|
import JA from '@/locales/ja.json'
|
||||||
import { useCanvasEvent } from '@/hooks/useCanvasEvent'
|
import { useCanvasEvent } from '@/hooks/useCanvasEvent'
|
||||||
import { popupState } from '@/store/popupAtom'
|
|
||||||
import SettingModal01 from '@/components/floor-plan/modal/setting01/SettingModal01'
|
import SettingModal01 from '@/components/floor-plan/modal/setting01/SettingModal01'
|
||||||
import { usePopup } from '@/hooks/usePopup'
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
import { placementShapeDrawingPointsState } from '@/store/placementShapeDrawingAtom'
|
import { placementShapeDrawingPointsState } from '@/store/placementShapeDrawingAtom'
|
||||||
import PlacementShapeSetting from '@/components/floor-plan/modal/placementShape/PlacementShapeSetting'
|
import PlacementShapeSetting from '@/components/floor-plan/modal/placementShape/PlacementShapeSetting'
|
||||||
import { useCommonUtils } from '@/hooks/common/useCommonUtils'
|
import { useCommonUtils } from '@/hooks/common/useCommonUtils'
|
||||||
|
|
||||||
const canvasMenus = [
|
import { commonUtilsState } from '@/store/commonUtilsAtom'
|
||||||
{ index: 0, name: 'plan.menu.plan.drawing', icon: 'con00', title: MENU.PLAN_DRAWING },
|
import { menusState, menuTypeState } from '@/store/menuAtom'
|
||||||
{ index: 1, name: 'plan.menu.placement.surface.initial.setting', icon: 'con01', title: MENU.INITIAL_CANVAS_SETTING },
|
import useMenu from '@/hooks/common/useMenu'
|
||||||
{ index: 2, name: 'plan.menu.roof.cover', icon: 'con02', title: MENU.ROOF_COVERING.DEFAULT },
|
import { MENU } from '@/common/common'
|
||||||
{ index: 3, name: 'plan.menu.placement.surface', icon: 'con03', title: MENU.BATCH_CANVAS.DEFAULT },
|
|
||||||
{ index: 4, name: 'plan.menu.module.circuit.setting', icon: 'con04', title: MENU.MODULE_CIRCUIT_SETTING.DEFAULT },
|
|
||||||
{ index: 5, name: 'plan.menu.estimate', icon: 'con06', title: MENU.ESTIMATE.DEFAULT },
|
|
||||||
{ index: 6, name: 'plan.menu.simulation', icon: 'con05', title: MENU.POWER_GENERATION_SIMULATION.DEFAULT },
|
|
||||||
]
|
|
||||||
|
|
||||||
export default function CanvasMenu(props) {
|
export default function CanvasMenu(props) {
|
||||||
const { menuNumber, setMenuNumber } = props
|
const { menuNumber, setMenuNumber } = props
|
||||||
|
const pathname = usePathname()
|
||||||
const { addPopup, closePopup } = usePopup()
|
const router = useRouter()
|
||||||
const [type, setType] = useState('')
|
const { addPopup } = usePopup()
|
||||||
|
const canvasMenus = useRecoilValue(menusState)
|
||||||
|
const [type, setType] = useRecoilState(menuTypeState)
|
||||||
const [verticalHorizontalMode, setVerticalHorizontalMode] = useRecoilState(verticalHorizontalModeState)
|
const [verticalHorizontalMode, setVerticalHorizontalMode] = useRecoilState(verticalHorizontalModeState)
|
||||||
const [appMessageState, setAppMessageState] = useRecoilState(appMessageStore)
|
const [appMessageState, setAppMessageState] = useRecoilState(appMessageStore)
|
||||||
const setCurrentMenu = useSetRecoilState(currentMenuState)
|
const setCurrentMenu = useSetRecoilState(currentMenuState)
|
||||||
const setOuterLinePoints = useSetRecoilState(outerLinePointsState)
|
const setOuterLinePoints = useSetRecoilState(outerLinePointsState)
|
||||||
const setPlacementPoints = useSetRecoilState(placementShapeDrawingPointsState)
|
const setPlacementPoints = useSetRecoilState(placementShapeDrawingPointsState)
|
||||||
|
const canvasSetting = useRecoilValue(canvasSettingState)
|
||||||
const [canvasZoom, setCanvasZoom] = useRecoilState(canvasZoomState)
|
const [canvasZoom, setCanvasZoom] = useRecoilState(canvasZoomState)
|
||||||
const [currentCanvasPlan, setcurrentCanvasPlan] = useRecoilState(currentCanvasPlanState)
|
const sessionState = useRecoilValue(sessionStore)
|
||||||
const { handleZoomClear } = useCanvasEvent()
|
|
||||||
|
|
||||||
const globalLocale = useRecoilValue(globalLocaleStore)
|
const globalLocale = useRecoilValue(globalLocaleStore)
|
||||||
const canvas = useRecoilValue(canvasState)
|
const canvas = useRecoilValue(canvasState)
|
||||||
const sessionState = useRecoilValue(sessionStore)
|
const { handleZoomClear } = useCanvasEvent()
|
||||||
|
const { handleMenu } = useMenu()
|
||||||
|
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
const { saveCanvas } = usePlan()
|
const { currentCanvasPlan, saveCanvas } = usePlan()
|
||||||
const { swalFire } = useSwal()
|
const { swalFire } = useSwal()
|
||||||
const { initEvent, addCanvasMouseEventListener, addDocumentEventListener } = useEvent()
|
const { initEvent, addCanvasMouseEventListener, addDocumentEventListener } = useEvent()
|
||||||
|
const commonUtils = useRecoilValue(commonUtilsState)
|
||||||
const [commonFunctionState, setCommonFunctionState] = useState({
|
const { commonFunctions } = useCommonUtils()
|
||||||
text: false,
|
|
||||||
dimension: false,
|
|
||||||
distance: false,
|
|
||||||
})
|
|
||||||
|
|
||||||
const { commonFunctions } = useCommonUtils({
|
|
||||||
commonFunctionState,
|
|
||||||
setCommonFunctionState,
|
|
||||||
})
|
|
||||||
|
|
||||||
const [popup, setPopup] = useRecoilState(popupState)
|
|
||||||
|
|
||||||
const SelectOption = [{ name: '瓦53A' }, { name: '瓦53A' }]
|
const SelectOption = [{ name: '瓦53A' }, { name: '瓦53A' }]
|
||||||
|
|
||||||
const onClickNav = (menu) => {
|
const onClickNav = (menu) => {
|
||||||
@ -96,9 +79,8 @@ export default function CanvasMenu(props) {
|
|||||||
setType('module')
|
setType('module')
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
|
||||||
const menuProps = {
|
if (pathname !== '/floor-plan') router.push('/floor-plan')
|
||||||
type,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const settingsModalOptions = useRecoilState(settingModalFirstOptionsState)
|
const settingsModalOptions = useRecoilState(settingModalFirstOptionsState)
|
||||||
@ -130,7 +112,6 @@ export default function CanvasMenu(props) {
|
|||||||
}
|
}
|
||||||
const onClickPlacementInitialMenu = () => {
|
const onClickPlacementInitialMenu = () => {
|
||||||
addPopup(placementInitialId, 1, <PlacementShapeSetting {...placementInitialProps} />)
|
addPopup(placementInitialId, 1, <PlacementShapeSetting {...placementInitialProps} />)
|
||||||
// setShowPlaceShapeModal(true)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleClear = () => {
|
const handleClear = () => {
|
||||||
@ -157,7 +138,19 @@ export default function CanvasMenu(props) {
|
|||||||
} else {
|
} else {
|
||||||
setAppMessageState(JA)
|
setAppMessageState(JA)
|
||||||
}
|
}
|
||||||
}, [menuNumber, type, globalLocale])
|
}, [type, globalLocale])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (['2', '3'].includes(canvasSetting?.roofSizeSet?.toString())) {
|
||||||
|
setMenuNumber(3)
|
||||||
|
setType('surface')
|
||||||
|
setCurrentMenu(MENU.BATCH_CANVAS.BATCH_DRAWING)
|
||||||
|
} else {
|
||||||
|
setMenuNumber(2)
|
||||||
|
setType('outline')
|
||||||
|
setCurrentMenu(MENU.ROOF_COVERING.EXTERIOR_WALL_LINE)
|
||||||
|
}
|
||||||
|
}, [canvasSetting])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`canvas-menu-wrap ${menuNumber === 2 || menuNumber === 3 || menuNumber === 4 ? 'active' : ''}`}>
|
<div className={`canvas-menu-wrap ${menuNumber === 2 || menuNumber === 3 || menuNumber === 4 ? 'active' : ''}`}>
|
||||||
@ -168,9 +161,12 @@ export default function CanvasMenu(props) {
|
|||||||
<li
|
<li
|
||||||
key={`canvas-menu-${menu.index}`}
|
key={`canvas-menu-${menu.index}`}
|
||||||
className={`canvas-menu-item ${menuNumber === menu.index ? 'active' : ''}`}
|
className={`canvas-menu-item ${menuNumber === menu.index ? 'active' : ''}`}
|
||||||
onClick={() => onClickNav(menu)}
|
onClick={() => {
|
||||||
|
if (['2', '3'].includes(canvasSetting?.roofSizeSet?.toString()) && menu.index === 2) return
|
||||||
|
onClickNav(menu)
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<button>
|
<button className={['2', '3'].includes(canvasSetting?.roofSizeSet?.toString()) && menu.index === 2 ? 'no-click' : ''}>
|
||||||
<span className={`menu-icon ${menu.icon}`}></span>
|
<span className={`menu-icon ${menu.icon}`}></span>
|
||||||
{getMessage(menu.name)}
|
{getMessage(menu.name)}
|
||||||
</button>
|
</button>
|
||||||
@ -188,9 +184,9 @@ export default function CanvasMenu(props) {
|
|||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
<div className="btn-from">
|
<div className="btn-from">
|
||||||
<button className={`btn01 ${commonFunctionState.text ? 'active' : ''}`} onClick={() => commonFunctions('text')}></button>
|
<button className={`btn01 ${commonUtils.text ? 'active' : ''}`} onClick={() => commonFunctions('text')}></button>
|
||||||
<button className={`btn02 ${commonFunctionState.dimension ? 'active' : ''} `} onClick={() => commonFunctions('dimension')}></button>
|
<button className={`btn02 ${commonUtils.dimension ? 'active' : ''} `} onClick={() => commonFunctions('dimension')}></button>
|
||||||
<button className={`btn03 ${commonFunctionState.distance ? 'active' : ''} `} onClick={() => commonFunctions('distance')}></button>
|
<button className={`btn03 ${commonUtils.distance ? 'active' : ''} `} onClick={() => commonFunctions('distance')}></button>
|
||||||
</div>
|
</div>
|
||||||
<div className="select-box">
|
<div className="select-box">
|
||||||
<QSelectBox title={'瓦53A'} option={SelectOption} />
|
<QSelectBox title={'瓦53A'} option={SelectOption} />
|
||||||
@ -224,7 +220,7 @@ export default function CanvasMenu(props) {
|
|||||||
<div className="ico-btn-from">
|
<div className="ico-btn-from">
|
||||||
<button className="btn-frame gray ico-flx act">
|
<button className="btn-frame gray ico-flx act">
|
||||||
<span className="ico ico01"></span>
|
<span className="ico ico01"></span>
|
||||||
<span>{getMessage('plan.menu.estimate.roof.alloc')}</span>
|
<span>{getMessage('plan.menu.estimate.docDown')}</span>
|
||||||
</button>
|
</button>
|
||||||
<button className="btn-frame gray ico-flx">
|
<button className="btn-frame gray ico-flx">
|
||||||
<span className="ico ico02"></span>
|
<span className="ico ico02"></span>
|
||||||
@ -258,7 +254,7 @@ export default function CanvasMenu(props) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={`canvas-depth2-wrap ${menuNumber === 2 || menuNumber === 3 || menuNumber === 4 ? 'active' : ''}`}>
|
<div className={`canvas-depth2-wrap ${menuNumber === 2 || menuNumber === 3 || menuNumber === 4 ? 'active' : ''}`}>
|
||||||
{(menuNumber === 2 || menuNumber === 3 || menuNumber === 4) && <MenuDepth01 {...menuProps} />}
|
{(menuNumber === 2 || menuNumber === 3 || menuNumber === 4) && <MenuDepth01 />}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -2,64 +2,35 @@
|
|||||||
|
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { useRecoilState, useRecoilValue } from 'recoil'
|
import { useRecoilState, useRecoilValue } from 'recoil'
|
||||||
import { useAxios } from '@/hooks/useAxios'
|
|
||||||
import { globalLocaleStore } from '@/store/localeAtom'
|
|
||||||
import { settingModalFirstOptionsState, settingModalSecondOptionsState } from '@/store/settingAtom'
|
import { settingModalFirstOptionsState, settingModalSecondOptionsState } from '@/store/settingAtom'
|
||||||
import CanvasMenu from '@/components/floor-plan/CanvasMenu'
|
import CanvasMenu from '@/components/floor-plan/CanvasMenu'
|
||||||
import CanvasLayout from '@/components/floor-plan/CanvasLayout'
|
import { useCanvasMenu } from '@/hooks/common/useCanvasMenu'
|
||||||
|
import { useCanvasSetting } from '@/hooks/option/useCanvasSetting'
|
||||||
import '@/styles/contents.scss'
|
import '@/styles/contents.scss'
|
||||||
|
|
||||||
export default function FloorPlan() {
|
export default function FloorPlan({ children }) {
|
||||||
const globalLocaleState = useRecoilValue(globalLocaleStore)
|
|
||||||
const { get } = useAxios(globalLocaleState)
|
|
||||||
const [settingModalFirstOptions, setSettingModalFirstOptions] = useRecoilState(settingModalFirstOptionsState)
|
const [settingModalFirstOptions, setSettingModalFirstOptions] = useRecoilState(settingModalFirstOptionsState)
|
||||||
const [settingModalSecondOptions, setSettingModalSecondOptions] = useRecoilState(settingModalSecondOptionsState)
|
const [settingModalSecondOptions, setSettingModalSecondOptions] = useRecoilState(settingModalSecondOptionsState)
|
||||||
const [objectNo, setObjectNo] = useState('test123240912001') // 이후 삭제 필요
|
const [objectNo, setObjectNo] = useState('test123240912001') // 이후 삭제 필요
|
||||||
|
|
||||||
const [menuNumber, setMenuNumber] = useState(null)
|
const { menuNumber, setMenuNumber } = useCanvasMenu()
|
||||||
|
|
||||||
|
const { fetchSettings } = useCanvasSetting()
|
||||||
|
|
||||||
const modalProps = {
|
const modalProps = {
|
||||||
menuNumber,
|
menuNumber,
|
||||||
setMenuNumber,
|
setMenuNumber,
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log('FloorPlan useEffect 실행')
|
|
||||||
fetchSettings()
|
fetchSettings()
|
||||||
}, [objectNo])
|
}, [objectNo])
|
||||||
|
|
||||||
// Canvas Setting 조회
|
|
||||||
const fetchSettings = async () => {
|
|
||||||
try {
|
|
||||||
const res = await get({ url: `/api/canvas-management/canvas-settings/by-object/${objectNo}` })
|
|
||||||
const optionData1 = settingModalFirstOptions.option1.map((item) => ({ ...item, selected: res[item.column] }))
|
|
||||||
const optionData2 = settingModalFirstOptions.option2.map((item) => ({ ...item, selected: res[item.column] }))
|
|
||||||
const optionData3 = settingModalSecondOptions.option3.map((item) => ({ ...item }))
|
|
||||||
const optionData4 = settingModalSecondOptions.option4.map((item) => ({ ...item, selected: res[item.column] }))
|
|
||||||
const optionData5 = settingModalFirstOptions.dimensionDisplay.map((item) => ({
|
|
||||||
...item,
|
|
||||||
}))
|
|
||||||
// 데이터 설정
|
|
||||||
setSettingModalFirstOptions({
|
|
||||||
option1: optionData1,
|
|
||||||
option2: optionData2,
|
|
||||||
dimensionDisplay: optionData5,
|
|
||||||
})
|
|
||||||
setSettingModalSecondOptions({
|
|
||||||
option3: optionData3,
|
|
||||||
option4: optionData4,
|
|
||||||
})
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Data fetching error:', error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="canvas-wrap">
|
<div className="canvas-wrap">
|
||||||
<CanvasMenu {...modalProps} />
|
<CanvasMenu {...modalProps} />
|
||||||
<div className={`canvas-content ${menuNumber === 2 || menuNumber === 3 || menuNumber === 4 ? 'active' : ''}`}>
|
<div className={`canvas-content ${menuNumber === 2 || menuNumber === 3 || menuNumber === 4 ? 'active' : ''}`}>{children}</div>
|
||||||
<CanvasLayout menuNumber={menuNumber} />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -1,150 +1,36 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import { useEffect, useState } from 'react'
|
|
||||||
import { MENU } from '@/common/common'
|
|
||||||
import { currentMenuState } from '@/store/canvasAtom'
|
import { currentMenuState } from '@/store/canvasAtom'
|
||||||
import { useSetRecoilState } from 'recoil'
|
import { useRecoilState, useRecoilValue } from 'recoil'
|
||||||
import { useSurfaceShapeBatch } from '@/hooks/surface/useSurfaceShapeBatch'
|
import { menuTypeState, subMenusState } from '@/store/menuAtom'
|
||||||
import { usePopup } from '@/hooks/usePopup'
|
import useMenu from '@/hooks/common/useMenu'
|
||||||
import { v4 as uuidv4 } from 'uuid'
|
import { useEffect } from 'react'
|
||||||
import WallLineSetting from '@/components/floor-plan/modal/outerlinesetting/WallLineSetting'
|
|
||||||
import RoofShapeSetting from '@/components/floor-plan/modal/roofShape/RoofShapeSetting'
|
|
||||||
import RoofShapePassivitySetting from '@/components/floor-plan/modal/roofShape/RoofShapePassivitySetting'
|
|
||||||
import AuxiliaryDrawing from '@/components/floor-plan/modal/auxiliary/AuxiliaryDrawing'
|
|
||||||
import EavesGableEdit from '@/components/floor-plan/modal/eavesGable/EavesGableEdit'
|
|
||||||
import MovementSetting from '@/components/floor-plan/modal/movement/MovementSetting'
|
|
||||||
import WallLineOffsetSetting from '@/components/floor-plan/modal/wallLineOffset/WallLineOffsetSetting'
|
|
||||||
import RoofAllocationSetting from '@/components/floor-plan/modal/roofAllocation/RoofAllocationSetting'
|
|
||||||
import Slope from '@/components/floor-plan/modal/Slope'
|
|
||||||
import ObjectSetting from '@/components/floor-plan/modal/object/ObjectSetting'
|
|
||||||
import PlacementShapeDrawing from '@/components/floor-plan/modal/placementShape/PlacementShapeDrawing'
|
|
||||||
import PlacementSurfaceSetting from '@/components/floor-plan/modal/placementSurface/PlacementSurfaceSetting'
|
|
||||||
import BasicSetting from '@/components/floor-plan/modal/basic/BasicSetting'
|
|
||||||
import CircuitTrestleSetting from '@/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting'
|
|
||||||
|
|
||||||
export default function MenuDepth01(props) {
|
export default function MenuDepth01() {
|
||||||
const { type } = props
|
const type = useRecoilValue(menuTypeState)
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
const [activeMenu, setActiveMenu] = useState()
|
const { handleMenu } = useMenu()
|
||||||
const setCurrentMenu = useSetRecoilState(currentMenuState)
|
const [currentMenu, setCurrentMenu] = useRecoilState(currentMenuState)
|
||||||
const { deleteAllSurfacesAndObjects } = useSurfaceShapeBatch()
|
const subMenus = useRecoilValue(subMenusState)
|
||||||
const { addPopup } = usePopup()
|
|
||||||
const [outlineId, setOutlineId] = useState(uuidv4())
|
const onClickMenu = ({ id, menu }) => {
|
||||||
const onClickMenu = ({ id, menu, name }) => {
|
if (menu === currentMenu) {
|
||||||
setActiveMenu(menu)
|
handleMenu(type)
|
||||||
|
} else {
|
||||||
setCurrentMenu(menu)
|
setCurrentMenu(menu)
|
||||||
if (type === 'outline') {
|
|
||||||
switch (id) {
|
|
||||||
case 0:
|
|
||||||
addPopup(outlineId, 1, <WallLineSetting id={outlineId} />)
|
|
||||||
break
|
|
||||||
case 1:
|
|
||||||
addPopup(outlineId, 1, <RoofShapeSetting id={outlineId} />)
|
|
||||||
break
|
|
||||||
case 2:
|
|
||||||
addPopup(outlineId, 1, <RoofShapePassivitySetting id={outlineId} />)
|
|
||||||
break
|
|
||||||
case 3:
|
|
||||||
addPopup(outlineId, 1, <AuxiliaryDrawing id={outlineId} />)
|
|
||||||
break
|
|
||||||
case 4:
|
|
||||||
addPopup(outlineId, 1, <EavesGableEdit id={outlineId} />)
|
|
||||||
break
|
|
||||||
case 5:
|
|
||||||
addPopup(outlineId, 1, <MovementSetting id={outlineId} />)
|
|
||||||
break
|
|
||||||
case 6:
|
|
||||||
addPopup(outlineId, 1, <WallLineOffsetSetting id={outlineId} />)
|
|
||||||
break
|
|
||||||
case 7:
|
|
||||||
addPopup(outlineId, 1, <RoofAllocationSetting id={outlineId} />)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type === 'surface') {
|
|
||||||
switch (id) {
|
|
||||||
case 0:
|
|
||||||
addPopup(outlineId, 1, <Slope id={outlineId} />)
|
|
||||||
break
|
|
||||||
case 1:
|
|
||||||
addPopup(outlineId, 1, <PlacementShapeDrawing id={outlineId} />)
|
|
||||||
break
|
|
||||||
case 2:
|
|
||||||
addPopup(outlineId, 1, <PlacementSurfaceSetting id={outlineId} />)
|
|
||||||
break
|
|
||||||
case 3:
|
|
||||||
addPopup(outlineId, 1, <ObjectSetting id={outlineId} />)
|
|
||||||
break
|
|
||||||
case 4:
|
|
||||||
deleteAllSurfacesAndObjects()
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type === 'module') {
|
|
||||||
switch (id) {
|
|
||||||
case 0:
|
|
||||||
addPopup(outlineId, 1, <BasicSetting id={outlineId} />)
|
|
||||||
break
|
|
||||||
case 1:
|
|
||||||
addPopup(outlineId, 1, <CircuitTrestleSetting id={outlineId} />)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setActiveMenu(null)
|
handleMenu(type)
|
||||||
}, [type])
|
}, [currentMenu])
|
||||||
|
|
||||||
const menuInfo = {
|
|
||||||
outline: [
|
|
||||||
// 지붕덮개
|
|
||||||
{ id: 0, name: 'plan.menu.roof.cover.outline.drawing', menu: MENU.ROOF_COVERING.EXTERIOR_WALL_LINE },
|
|
||||||
{ id: 1, name: 'plan.menu.roof.cover.roof.shape.setting', menu: MENU.ROOF_COVERING.ROOF_SHAPE_SETTINGS },
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
name: 'plan.menu.roof.cover.roof.shape.passivity.setting',
|
|
||||||
menu: MENU.ROOF_COVERING.ROOF_SHAPE_PASSIVITY_SETTINGS,
|
|
||||||
},
|
|
||||||
{ id: 3, name: 'plan.menu.roof.cover.auxiliary.line.drawing', menu: MENU.ROOF_COVERING.HELP_LINE_DRAWING },
|
|
||||||
{ id: 4, name: 'plan.menu.roof.cover.eaves.kerava.edit', menu: MENU.ROOF_COVERING.EAVES_KERAVA_EDIT },
|
|
||||||
{ id: 5, name: 'plan.menu.roof.cover.movement.shape.updown', menu: MENU.ROOF_COVERING.MOVEMENT_SHAPE_UPDOWN },
|
|
||||||
{ id: 6, name: 'plan.menu.roof.cover.outline.edit.offset', menu: MENU.ROOF_COVERING.OUTLINE_EDIT_OFFSET },
|
|
||||||
{ id: 7, name: 'plan.menu.roof.cover.roof.surface.alloc', menu: MENU.ROOF_COVERING.ROOF_SHAPE_ALLOC },
|
|
||||||
],
|
|
||||||
surface: [
|
|
||||||
// 배치면
|
|
||||||
{ id: 0, name: 'plan.menu.placement.surface.slope.setting', menu: MENU.BATCH_CANVAS.SLOPE_SETTING },
|
|
||||||
{ id: 1, name: 'plan.menu.placement.surface.drawing', menu: MENU.BATCH_CANVAS.BATCH_DRAWING },
|
|
||||||
{ id: 2, name: 'plan.menu.placement.surface.arrangement', menu: MENU.BATCH_CANVAS.SURFACE_SHAPE_BATCH },
|
|
||||||
{ id: 3, name: 'plan.menu.placement.surface.object', menu: MENU.BATCH_CANVAS.OBJECT_BATCH },
|
|
||||||
{ id: 4, name: 'plan.menu.placement.surface.all.remove', menu: MENU.BATCH_CANVAS.ALL_REMOVE },
|
|
||||||
],
|
|
||||||
module: [
|
|
||||||
// 모듈, 회로 구성
|
|
||||||
|
|
||||||
{ id: 0, name: 'plan.menu.module.circuit.setting.default', menu: MENU.MODULE_CIRCUIT_SETTING.BASIC_SETTING },
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
name: 'plan.menu.module.circuit.setting.circuit.trestle.setting',
|
|
||||||
menu: MENU.MODULE_CIRCUIT_SETTING.CIRCUIT_TRESTLE_SETTING,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
name: 'plan.menu.module.circuit.setting.plan.orientation',
|
|
||||||
menu: MENU.MODULE_CIRCUIT_SETTING.PLAN_ORIENTATION,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
||||||
return (
|
return (
|
||||||
<div className="canvas-depth2-inner">
|
<div className="canvas-depth2-inner">
|
||||||
<ul className="canvas-depth2-list">
|
<ul className="canvas-depth2-list">
|
||||||
{menuInfo[type].map((menu) => {
|
{subMenus[type]?.map((menu) => {
|
||||||
return (
|
return (
|
||||||
<li key={menu.id} className={`canvas-depth2-item ${menu.menu === activeMenu ? 'active' : ''}`}>
|
<li key={menu.id} className={`canvas-depth2-item ${menu.menu === currentMenu ? 'active' : ''}`}>
|
||||||
<button onClick={() => onClickMenu(menu)}>{getMessage(menu.name)}</button>
|
<button onClick={() => onClickMenu(menu)}>{getMessage(menu.name)}</button>
|
||||||
</li>
|
</li>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import WithDraggable from '@/components/common/draggable/WithDraggable'
|
import WithDraggable from '@/components/common/draggable/WithDraggable'
|
||||||
import { globalPitchState } from '@/store/canvasAtom'
|
import { globalPitchState, pitchSelector, pitchTextSelector } from '@/store/canvasAtom'
|
||||||
import { useRecoilState } from 'recoil'
|
import { useRecoilState } from 'recoil'
|
||||||
import { useRef } from 'react'
|
import { useRef } from 'react'
|
||||||
import { usePopup } from '@/hooks/usePopup'
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
@ -8,7 +8,8 @@ import { usePopup } from '@/hooks/usePopup'
|
|||||||
export default function Slope({ id, pos = { x: 50, y: 230 } }) {
|
export default function Slope({ id, pos = { x: 50, y: 230 } }) {
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
const { closePopup } = usePopup()
|
const { closePopup } = usePopup()
|
||||||
const [globalPitch, setGlobalPitch] = useRecoilState(globalPitchState)
|
const [globalPitch, setGlobalPitch] = useRecoilState(pitchSelector)
|
||||||
|
const pitchText = useRecoilState(pitchTextSelector)
|
||||||
const inputRef = useRef()
|
const inputRef = useRef()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -29,7 +30,7 @@ export default function Slope({ id, pos = { x: 50, y: 230 } }) {
|
|||||||
<div className="input-grid mr5">
|
<div className="input-grid mr5">
|
||||||
<input type="text" className="input-origin block" defaultValue={globalPitch} ref={inputRef} />
|
<input type="text" className="input-origin block" defaultValue={globalPitch} ref={inputRef} />
|
||||||
</div>
|
</div>
|
||||||
<span className="thin">{getMessage('size.angle')}</span>
|
<span className="thin">{pitchText}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid-btn-wrap">
|
<div className="grid-btn-wrap">
|
||||||
|
|||||||
@ -3,50 +3,79 @@ import WithDraggable from '@/components/common/draggable/WithDraggable'
|
|||||||
import { usePopup } from '@/hooks/usePopup'
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
import { useRecoilValue } from 'recoil'
|
import { useRecoilValue } from 'recoil'
|
||||||
import { contextPopupPositionState } from '@/store/popupAtom'
|
import { contextPopupPositionState } from '@/store/popupAtom'
|
||||||
|
import { useState } from 'react'
|
||||||
|
|
||||||
export default function AuxiliaryCopy(props) {
|
export default function AuxiliaryCopy(props) {
|
||||||
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
||||||
const { id, pos = contextPopupPosition } = props
|
const { id, pos = contextPopupPosition } = props
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
const { closePopup } = usePopup()
|
const { closePopup } = usePopup()
|
||||||
|
const [arrow1, setArrow1] = useState(null)
|
||||||
|
const [arrow2, setArrow2] = useState(null)
|
||||||
return (
|
return (
|
||||||
<WithDraggable isShow={true} pos={pos}>
|
<WithDraggable isShow={true} pos={pos}>
|
||||||
<div className={`modal-pop-wrap xm`}>
|
<div className={`modal-pop-wrap xm mount`}>
|
||||||
<div className="modal-head">
|
<div className="modal-head">
|
||||||
<h1 className="title">補助線のコピー </h1>
|
<h1 className="title">{getMessage('modal.auxiliary.copy')} </h1>
|
||||||
<button className="modal-close" onClick={() => closePopup(id)}>
|
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||||
닫기
|
닫기
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="modal-body">
|
<div className="modal-body">
|
||||||
<div className="grid-option-tit">コピーする方向を入力してください</div>
|
<div className="grid-option-tit">{getMessage('modal.auxiliary.copy.info')}</div>
|
||||||
<div className="grid-option-wrap">
|
<div className="grid-option-wrap">
|
||||||
<div className="grid-option-box">
|
<div className="grid-option-box">
|
||||||
<div className="move-form">
|
<div className="move-form">
|
||||||
<p className="mb5">長さ</p>
|
<p className="mb5">{getMessage('length')}</p>
|
||||||
<div className="input-move-wrap mb5">
|
<div className="input-move-wrap mb5">
|
||||||
<div className="input-move">
|
<div className="input-move">
|
||||||
<input type="text" className="input-origin" defaultValue={910} />
|
<input type="text" className="input-origin" defaultValue={910} />
|
||||||
</div>
|
</div>
|
||||||
<span>mm</span>
|
<span>mm</span>
|
||||||
|
<div className="direction-move-wrap">
|
||||||
|
<button
|
||||||
|
className={`direction up ${arrow1 === '↑' ? 'act' : ''}`}
|
||||||
|
onClick={() => {
|
||||||
|
setArrow1('↑')
|
||||||
|
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowUp' }))
|
||||||
|
}}
|
||||||
|
></button>
|
||||||
|
<button
|
||||||
|
className={`direction down ${arrow1 === '↓' ? 'act' : ''}`}
|
||||||
|
onClick={() => {
|
||||||
|
setArrow1('↓')
|
||||||
|
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown' }))
|
||||||
|
}}
|
||||||
|
></button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="input-move-wrap">
|
<div className="input-move-wrap">
|
||||||
<div className="input-move">
|
<div className="input-move">
|
||||||
<input type="text" className="input-origin" defaultValue={910} />
|
<input type="text" className="input-origin" defaultValue={910} />
|
||||||
</div>
|
</div>
|
||||||
<span>mm</span>
|
<span>mm</span>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="direction-move-wrap">
|
<div className="direction-move-wrap">
|
||||||
<button className="direction up"></button>
|
<button
|
||||||
<button className="direction down act"></button>
|
className={`direction left ${arrow2 === '←' ? 'act' : ''}`}
|
||||||
<button className="direction left"></button>
|
onClick={() => {
|
||||||
<button className="direction right"></button>
|
setArrow2('←')
|
||||||
|
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowLeft' }))
|
||||||
|
}}
|
||||||
|
></button>
|
||||||
|
<button
|
||||||
|
className={`direction right ${arrow2 === '→' ? 'act' : ''}`}
|
||||||
|
onClick={() => {
|
||||||
|
setArrow2('→')
|
||||||
|
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowRight' }))
|
||||||
|
}}
|
||||||
|
></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid-btn-wrap">
|
<div className="grid-btn-wrap">
|
||||||
<button className="btn-frame modal act">保存</button>
|
<button className="btn-frame modal act">{getMessage('modal.common.save')}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,52 +1,83 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import WithDraggable from '@/components/common/draggable/WithDraggable'
|
import WithDraggable from '@/components/common/draggable/WithDraggable'
|
||||||
import { useRecoilValue } from 'recoil'
|
import { useRecoilValue } from 'recoil'
|
||||||
import { contextPopupPositionState } from '@/store/popupAtom'
|
import { contextPopupPositionState } from '@/store/popupAtom'
|
||||||
import { usePopup } from '@/hooks/usePopup'
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
|
import { useState } from 'react'
|
||||||
|
|
||||||
export default function AuxiliaryMove(props) {
|
export default function AuxiliaryMove(props) {
|
||||||
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
||||||
const { id, pos = contextPopupPosition } = props
|
const { id, pos = contextPopupPosition } = props
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
const { closePopup } = usePopup()
|
const { closePopup } = usePopup()
|
||||||
|
const [arrow1, setArrow1] = useState(null)
|
||||||
|
const [arrow2, setArrow2] = useState(null)
|
||||||
return (
|
return (
|
||||||
<WithDraggable isShow={true} pos={pos}>
|
<WithDraggable isShow={true} pos={pos}>
|
||||||
<div className={`modal-pop-wrap xm`}>
|
<div className={`modal-pop-wrap xm mount`}>
|
||||||
<div className="modal-head">
|
<div className="modal-head">
|
||||||
<h1 className="title">補助線の移動 </h1>
|
<h1 className="title">{getMessage('modal.auxiliary.move')}</h1>
|
||||||
<button className="modal-close" onClick={() => closePopup(id)}>
|
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||||
닫기
|
닫기
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="modal-body">
|
<div className="modal-body">
|
||||||
<div className="grid-option-tit">移動する方向を入力してください</div>
|
<div className="grid-option-tit">{getMessage('modal.auxiliary.move.info')}</div>
|
||||||
<div className="grid-option-wrap">
|
<div className="grid-option-wrap">
|
||||||
<div className="grid-option-box">
|
<div className="grid-option-box">
|
||||||
<div className="move-form">
|
<div className="move-form">
|
||||||
<p className="mb5">長さ</p>
|
<p className="mb5">{getMessage('length')}</p>
|
||||||
<div className="input-move-wrap mb5">
|
<div className="input-move-wrap mb5">
|
||||||
<div className="input-move">
|
<div className="input-move">
|
||||||
<input type="text" className="input-origin" defaultValue={910} />
|
<input type="text" className="input-origin" defaultValue={910} />
|
||||||
</div>
|
</div>
|
||||||
<span>mm</span>
|
<span>mm</span>
|
||||||
|
<div className="direction-move-wrap">
|
||||||
|
<button
|
||||||
|
className={`direction up ${arrow1 === '↑' ? 'act' : ''}`}
|
||||||
|
onClick={() => {
|
||||||
|
setArrow1('↑')
|
||||||
|
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowUp' }))
|
||||||
|
}}
|
||||||
|
></button>
|
||||||
|
<button
|
||||||
|
className={`direction down ${arrow1 === '↓' ? 'act' : ''}`}
|
||||||
|
onClick={() => {
|
||||||
|
setArrow1('↓')
|
||||||
|
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown' }))
|
||||||
|
}}
|
||||||
|
></button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="input-move-wrap">
|
<div className="input-move-wrap">
|
||||||
<div className="input-move">
|
<div className="input-move">
|
||||||
<input type="text" className="input-origin" defaultValue={910} />
|
<input type="text" className="input-origin" defaultValue={910} />
|
||||||
</div>
|
</div>
|
||||||
<span>mm</span>
|
<span>mm</span>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="direction-move-wrap">
|
<div className="direction-move-wrap">
|
||||||
<button className="direction up"></button>
|
<button
|
||||||
<button className="direction down act"></button>
|
className={`direction left ${arrow2 === '←' ? 'act' : ''}`}
|
||||||
<button className="direction left"></button>
|
onClick={() => {
|
||||||
<button className="direction right"></button>
|
setArrow2('←')
|
||||||
|
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowLeft' }))
|
||||||
|
}}
|
||||||
|
></button>
|
||||||
|
<button
|
||||||
|
className={`direction right ${arrow2 === '→' ? 'act' : ''}`}
|
||||||
|
onClick={() => {
|
||||||
|
setArrow2('→')
|
||||||
|
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowRight' }))
|
||||||
|
}}
|
||||||
|
></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid-btn-wrap">
|
<div className="grid-btn-wrap">
|
||||||
<button className="btn-frame modal act">保存</button>
|
<button className="btn-frame modal act">{getMessage('modal.common.save')}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -11,9 +11,9 @@ export default function AuxiliarySize(props) {
|
|||||||
const { closePopup } = usePopup()
|
const { closePopup } = usePopup()
|
||||||
return (
|
return (
|
||||||
<WithDraggable isShow={true} pos={pos}>
|
<WithDraggable isShow={true} pos={pos}>
|
||||||
<div className={`modal-pop-wrap xm`}>
|
<div className={`modal-pop-wrap xm mount`}>
|
||||||
<div className="modal-head">
|
<div className="modal-head">
|
||||||
<h1 className="title">補助線サイズ変更 </h1>
|
<h1 className="title">{getMessage('modal.auxiliary.size.edit')} </h1>
|
||||||
<button className="modal-close" onClick={() => closePopup(id)}>
|
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||||
닫기
|
닫기
|
||||||
</button>
|
</button>
|
||||||
@ -22,7 +22,7 @@ export default function AuxiliarySize(props) {
|
|||||||
<div className="discrimination-box mb10">
|
<div className="discrimination-box mb10">
|
||||||
<div className="d-check-radio pop mb10">
|
<div className="d-check-radio pop mb10">
|
||||||
<input type="radio" name="radio01" id="ra01" />
|
<input type="radio" name="radio01" id="ra01" />
|
||||||
<label htmlFor="ra01">1支店</label>
|
<label htmlFor="ra01">1{getMessage('modal.auxiliary.size.edit.point')}</label>
|
||||||
</div>
|
</div>
|
||||||
<div className="outline-form mb15">
|
<div className="outline-form mb15">
|
||||||
<div className="input-grid mr5" style={{ flex: '1 1 auto' }}>
|
<div className="input-grid mr5" style={{ flex: '1 1 auto' }}>
|
||||||
@ -31,7 +31,7 @@ export default function AuxiliarySize(props) {
|
|||||||
<span className="thin">mm</span>
|
<span className="thin">mm</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="outline-form">
|
<div className="outline-form">
|
||||||
<span style={{ width: 'auto' }}>長さ</span>
|
<span style={{ width: 'auto' }}>{getMessage('length')}</span>
|
||||||
<div className="input-grid mr5">
|
<div className="input-grid mr5">
|
||||||
<input type="text" className="input-origin block" defaultValue={100} />
|
<input type="text" className="input-origin block" defaultValue={100} />
|
||||||
</div>
|
</div>
|
||||||
@ -41,7 +41,7 @@ export default function AuxiliarySize(props) {
|
|||||||
<div className="discrimination-box ">
|
<div className="discrimination-box ">
|
||||||
<div className="d-check-radio pop mb10">
|
<div className="d-check-radio pop mb10">
|
||||||
<input type="radio" name="radio01" id="ra02" />
|
<input type="radio" name="radio01" id="ra02" />
|
||||||
<label htmlFor="ra02">2支店</label>
|
<label htmlFor="ra02">2{getMessage('modal.auxiliary.size.edit.point')}</label>
|
||||||
</div>
|
</div>
|
||||||
<div className="outline-form mb15">
|
<div className="outline-form mb15">
|
||||||
<div className="input-grid mr5" style={{ flex: '1 1 auto' }}>
|
<div className="input-grid mr5" style={{ flex: '1 1 auto' }}>
|
||||||
@ -50,7 +50,7 @@ export default function AuxiliarySize(props) {
|
|||||||
<span className="thin">mm</span>
|
<span className="thin">mm</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="outline-form">
|
<div className="outline-form">
|
||||||
<span style={{ width: 'auto' }}>長さ</span>
|
<span style={{ width: 'auto' }}>{getMessage('length')}</span>
|
||||||
<div className="input-grid mr5">
|
<div className="input-grid mr5">
|
||||||
<input type="text" className="input-origin block" defaultValue={100} />
|
<input type="text" className="input-origin block" defaultValue={100} />
|
||||||
</div>
|
</div>
|
||||||
@ -58,7 +58,7 @@ export default function AuxiliarySize(props) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid-btn-wrap">
|
<div className="grid-btn-wrap">
|
||||||
<button className="btn-frame modal act">保存</button>
|
<button className="btn-frame modal act">{getMessage('modal.common.save')}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,71 +1,144 @@
|
|||||||
|
import { useEffect, useRef, useState } from 'react'
|
||||||
import WithDraggable from '@/components/common/draggable/WithDraggable'
|
import WithDraggable from '@/components/common/draggable/WithDraggable'
|
||||||
import { usePopup } from '@/hooks/usePopup'
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import { useRecoilValue } from 'recoil'
|
import { useRecoilState, useRecoilValue } from 'recoil'
|
||||||
import { contextPopupPositionState } from '@/store/popupAtom'
|
import { contextPopupPositionState } from '@/store/popupAtom'
|
||||||
import QSelectBox from '@/components/common/select/QSelectBox'
|
import QSelectBox from '@/components/common/select/QSelectBox'
|
||||||
|
import { canvasState, pitchTextSelector } from '@/store/canvasAtom'
|
||||||
|
import { defaultSlope } from '@/store/commonAtom'
|
||||||
|
|
||||||
export default function DimensionLineSetting(props) {
|
export default function DimensionLineSetting(props) {
|
||||||
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
||||||
const { id, setIsShow, pos = contextPopupPosition } = props
|
let { id, setIsShow, pos = contextPopupPosition } = props
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
const { closePopup } = usePopup()
|
const { closePopup } = usePopup()
|
||||||
const SelectOption01 = [{ name: '0' }, { name: '0' }, { name: '0' }, { name: '0' }]
|
const canvas = useRecoilValue(canvasState)
|
||||||
|
const pitchText = useRecoilState(pitchTextSelector)
|
||||||
|
const SelectOption01 = defaultSlope
|
||||||
|
const [basicLength, setBasicLength] = useState(0)
|
||||||
|
const [slopeAble, setSlopeAble] = useState(false)
|
||||||
|
const changeSlopeRef = useRef()
|
||||||
|
|
||||||
|
let slopeInput1, slopeInput2
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (canvas) {
|
||||||
|
const dimensionObject = canvas.getActiveObject()
|
||||||
|
const id = dimensionObject.groupId
|
||||||
|
const textObj = dimensionObject._objects.filter((obj) => obj.name === 'dimensionLineText' && obj.id === id)[0]
|
||||||
|
setBasicLength(parseInt(textObj.text))
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
setBasicLength(0)
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const handleChangeLength = () => {
|
||||||
|
const changeLength = changeSlopeRef.current
|
||||||
|
|
||||||
|
if (canvas) {
|
||||||
|
const dimensionObject = canvas.getActiveObject()
|
||||||
|
const id = dimensionObject.groupId
|
||||||
|
const textObj = dimensionObject._objects.filter((obj) => obj.name === 'dimensionLineText' && obj.id === id)[0]
|
||||||
|
let resultText = changeLength.value > 0 ? changeLength.value : '0'
|
||||||
|
|
||||||
|
if (slopeAble) {
|
||||||
|
if (slopeInput1) {
|
||||||
|
resultText = calculateLength(basicLength, slopeInput1.angleValue).toFixed(0)
|
||||||
|
|
||||||
|
if (slopeInput2) {
|
||||||
|
const length = calculateLength(basicLength, slopeInput1.angleValue, slopeInput2.angleValue)
|
||||||
|
resultText = length.toFixed(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
textObj.set({
|
||||||
|
text: String(resultText),
|
||||||
|
})
|
||||||
|
|
||||||
|
canvas.renderAll()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSelectbox = (option, params) => {
|
||||||
|
const index = params.index
|
||||||
|
if (index === 1) slopeInput1 = option
|
||||||
|
if (index === 2) slopeInput2 = option
|
||||||
|
}
|
||||||
|
|
||||||
|
function calculateLength(originalLength, angle) {
|
||||||
|
const angleInRadians = angle * (Math.PI / 180)
|
||||||
|
const result = Math.sqrt(Math.pow(originalLength * Math.tan(angleInRadians), 2) + Math.pow(originalLength, 2))
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
function calculateLength(originalLength, angle1, angle2) {
|
||||||
|
const numerator = Math.sqrt(Math.pow(angle1, 2) + 100 + Math.pow((10 * angle1) / angle2, 2)) * originalLength
|
||||||
|
const denominator = Math.sqrt(Math.pow((10 * angle1) / angle2, 2) + 100)
|
||||||
|
const result = numerator / denominator
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<WithDraggable isShow={true} pos={pos}>
|
<WithDraggable isShow={true} pos={pos}>
|
||||||
<div className={`modal-pop-wrap xm`}>
|
<div className={`modal-pop-wrap xm mount`}>
|
||||||
<div className="modal-head">
|
<div className="modal-head">
|
||||||
<h1 className="title">表示の変更 </h1>
|
<h1 className="title">{getMessage('contextmenu.display.edit')} </h1>
|
||||||
<button className="modal-close" onClick={() => closePopup(id)}>
|
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||||
닫기
|
닫기
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="modal-body">
|
<div className="modal-body">
|
||||||
<div className="guide">寸法線に表示する数値を入力してください</div>
|
<div className="guide">{getMessage('modal.display.edit.info')}</div>
|
||||||
<div className="mb-box">
|
<div className="mb-box">
|
||||||
<div className="slope-wrap">
|
<div className="slope-wrap">
|
||||||
<div className="outline-form mb15">
|
<div className="outline-form mb15">
|
||||||
<span className="mr10">既存の長さ</span>
|
<span className="mr10">{getMessage('modal.display.edit.before.length')}</span>
|
||||||
<div className="input-grid mr5">
|
<div className="input-grid mr5">
|
||||||
<input type="text" className="input-origin block" defaultValue={5933} readOnly />
|
<input type="text" className="input-origin block" value={basicLength} readOnly />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-box">
|
<div className="mb-box">
|
||||||
<div className="outline-form">
|
<div className="outline-form">
|
||||||
<span className="mr10">変更の長さ</span>
|
<span className="mr10">{getMessage('modal.display.edit.after.length')}</span>
|
||||||
<div className="input-grid mr5">
|
<div className="input-grid mr5">
|
||||||
<input type="text" className="input-origin block" defaultValue={0} />
|
<input type="text" className="input-origin block" ref={changeSlopeRef} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="d-check-box pop">
|
<div className="d-check-box pop">
|
||||||
<input type="checkbox" id="ch99" />
|
<input type="checkbox" id="ch99" onChange={() => setSlopeAble(!slopeAble)} />
|
||||||
<label htmlFor="ch99">コーナー・ゴールの場合</label>
|
<label htmlFor="ch99">{getMessage('modal.display.edit.input.slope')}</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="slope-wrap">
|
<div className="slope-wrap">
|
||||||
<div className="warning">傾斜を着せてください。</div>
|
<div className="warning">{getMessage('modal.display.edit.input.slope')}</div>
|
||||||
<div className="display-change-wrap">
|
<div className="display-change-wrap">
|
||||||
<div className="outline-form mb15">
|
<div className="outline-form mb15">
|
||||||
<span className="mr10">傾斜</span>
|
<span className="mr10">{getMessage('slope')}</span>
|
||||||
<div className="grid-select mr10">
|
<div className="grid-select mr10">
|
||||||
<QSelectBox title={'0'} option={SelectOption01} />
|
<QSelectBox title={''} options={SelectOption01} disabled={!slopeAble} params={{ index: 1 }} onChange={handleSelectbox} />
|
||||||
</div>
|
</div>
|
||||||
<span className="thin">寸法</span>
|
<span className="thin">{pitchText}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="outline-form">
|
<div className="outline-form">
|
||||||
<span className="mr10">傾斜</span>
|
<span className="mr10">{getMessage('slope')}</span>
|
||||||
<div className="grid-select mr10">
|
<div className="grid-select mr10">
|
||||||
<QSelectBox title={'0'} option={SelectOption01} />
|
<QSelectBox title={''} options={SelectOption01} disabled={!slopeAble} params={{ index: 2 }} onChange={handleSelectbox} />
|
||||||
</div>
|
</div>
|
||||||
<span className="thin">寸法</span>
|
<span className="thin">{pitchText}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="warning">傾き設定されている場合、入力した数値に傾き計算をした数値が表示されます。</div>
|
<div className="warning">{getMessage('modal.display.edit.input.slope.info')}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid-btn-wrap">
|
<div className="grid-btn-wrap">
|
||||||
<button className="btn-frame modal act">保存</button>
|
<button className="btn-frame modal act" onClick={handleChangeLength}>
|
||||||
|
{getMessage('modal.common.save')}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,20 +1,25 @@
|
|||||||
import WithDraggable from '@/components/common/draggable/withDraggable'
|
import { useRecoilValue } from 'recoil'
|
||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import { usePopup } from '@/hooks/usePopup'
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
import { useRecoilValue } from 'recoil'
|
import WithDraggable from '@/components/common/draggable/WithDraggable'
|
||||||
import { contextPopupPositionState } from '@/store/popupAtom'
|
import { contextPopupPositionState } from '@/store/popupAtom'
|
||||||
|
|
||||||
export default function Distance(props) {
|
export default function Distance(props) {
|
||||||
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
||||||
const { id, pos = contextPopupPosition, distance } = props
|
const { id, pos = contextPopupPosition, distance, deleteDistance } = props
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
const { closePopup } = usePopup()
|
const { closePopup } = usePopup()
|
||||||
|
|
||||||
|
const handleClose = () => {
|
||||||
|
deleteDistance()
|
||||||
|
closePopup(id)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<WithDraggable isShow={true} pos={pos}>
|
<WithDraggable isShow={true} pos={pos}>
|
||||||
<div className={`modal-pop-wrap xxxm`}>
|
<div className={`modal-pop-wrap xxxm`}>
|
||||||
<div className="modal-head">
|
<div className="modal-head">
|
||||||
<h1 className="title">距離測定 </h1>
|
<h1 className="title">{getMessage('modal.distance')} </h1>
|
||||||
<button className="modal-close" onClick={() => closePopup(id)}>
|
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||||
닫기
|
닫기
|
||||||
</button>
|
</button>
|
||||||
@ -23,7 +28,7 @@ export default function Distance(props) {
|
|||||||
<div className="slope-wrap">
|
<div className="slope-wrap">
|
||||||
<div className="eaves-keraba-table">
|
<div className="eaves-keraba-table">
|
||||||
<div className="eaves-keraba-item">
|
<div className="eaves-keraba-item">
|
||||||
<div className="eaves-keraba-th">2点間距離</div>
|
<div className="eaves-keraba-th">{getMessage('modal.distance.dual.point')}</div>
|
||||||
<div className="eaves-keraba-td">
|
<div className="eaves-keraba-td">
|
||||||
<div className="outline-form">
|
<div className="outline-form">
|
||||||
<div className="input-grid mr5" style={{ width: '98px' }}>
|
<div className="input-grid mr5" style={{ width: '98px' }}>
|
||||||
@ -34,7 +39,7 @@ export default function Distance(props) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="eaves-keraba-item">
|
<div className="eaves-keraba-item">
|
||||||
<div className="eaves-keraba-th">水平距離</div>
|
<div className="eaves-keraba-th">{getMessage('modal.distance.horizon')}</div>
|
||||||
<div className="eaves-keraba-td">
|
<div className="eaves-keraba-td">
|
||||||
<div className="outline-form">
|
<div className="outline-form">
|
||||||
<div className="input-grid mr5" style={{ width: '98px' }}>
|
<div className="input-grid mr5" style={{ width: '98px' }}>
|
||||||
@ -45,7 +50,7 @@ export default function Distance(props) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="eaves-keraba-item">
|
<div className="eaves-keraba-item">
|
||||||
<div className="eaves-keraba-th">垂直距離</div>
|
<div className="eaves-keraba-th">{getMessage('modal.distance.vertical')}</div>
|
||||||
<div className="eaves-keraba-td">
|
<div className="eaves-keraba-td">
|
||||||
<div className="outline-form">
|
<div className="outline-form">
|
||||||
<div className="input-grid mr5" style={{ width: '98px' }}>
|
<div className="input-grid mr5" style={{ width: '98px' }}>
|
||||||
@ -58,7 +63,7 @@ export default function Distance(props) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid-btn-wrap">
|
<div className="grid-btn-wrap">
|
||||||
<button className="btn-frame modal act">確認</button>
|
<button className="btn-frame modal act" onClick={handleClose}>{getMessage('common.require')}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -11,12 +11,13 @@ export default function EavesGableEdit({ id, pos = { x: 50, y: 230 } }) {
|
|||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
const { closePopup } = usePopup()
|
const { closePopup } = usePopup()
|
||||||
|
|
||||||
const { type, setType, buttonMenu, TYPES, pitchRef, offsetRef, widthRef, radioTypeRef } = useEavesGableEdit(id)
|
const { type, setType, buttonMenu, TYPES, pitchRef, offsetRef, widthRef, radioTypeRef, pitchText } = useEavesGableEdit(id)
|
||||||
const eavesProps = {
|
const eavesProps = {
|
||||||
pitchRef,
|
pitchRef,
|
||||||
offsetRef,
|
offsetRef,
|
||||||
widthRef,
|
widthRef,
|
||||||
radioTypeRef,
|
radioTypeRef,
|
||||||
|
pitchText,
|
||||||
}
|
}
|
||||||
|
|
||||||
const gableProps = {
|
const gableProps = {
|
||||||
@ -24,6 +25,7 @@ export default function EavesGableEdit({ id, pos = { x: 50, y: 230 } }) {
|
|||||||
offsetRef,
|
offsetRef,
|
||||||
widthRef,
|
widthRef,
|
||||||
radioTypeRef,
|
radioTypeRef,
|
||||||
|
pitchText,
|
||||||
}
|
}
|
||||||
|
|
||||||
const wallMergeProps = {
|
const wallMergeProps = {
|
||||||
|
|||||||
@ -1,14 +1,17 @@
|
|||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import Image from 'next/image'
|
import Image from 'next/image'
|
||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
|
import { useRecoilValue } from 'recoil'
|
||||||
|
import { ANGLE_TYPE, currentAngleTypeSelector } from '@/store/canvasAtom'
|
||||||
|
|
||||||
export default function Eaves({ pitchRef, offsetRef, widthRef, radioTypeRef }) {
|
export default function Eaves({ pitchRef, offsetRef, widthRef, radioTypeRef, pitchText }) {
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
const [type, setType] = useState('1')
|
const [type, setType] = useState('1')
|
||||||
const onChange = (e) => {
|
const onChange = (e) => {
|
||||||
setType(e.target.value)
|
setType(e.target.value)
|
||||||
radioTypeRef.current = e.target.value
|
radioTypeRef.current = e.target.value
|
||||||
}
|
}
|
||||||
|
const currentAngleType = useRecoilValue(currentAngleTypeSelector)
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="outline-wrap">
|
<div className="outline-wrap">
|
||||||
@ -17,9 +20,9 @@ export default function Eaves({ pitchRef, offsetRef, widthRef, radioTypeRef }) {
|
|||||||
{getMessage('slope')}
|
{getMessage('slope')}
|
||||||
</span>
|
</span>
|
||||||
<div className="input-grid mr5" style={{ width: '100px' }}>
|
<div className="input-grid mr5" style={{ width: '100px' }}>
|
||||||
<input type="number" className="input-origin block" defaultValue={4} ref={pitchRef} />
|
<input type="number" className="input-origin block" defaultValue={currentAngleType === ANGLE_TYPE.SLOPE ? 4 : 21.8} ref={pitchRef} />
|
||||||
</div>
|
</div>
|
||||||
<span className="thin">寸</span>
|
<span className="thin">{pitchText}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="outline-form">
|
<div className="outline-form">
|
||||||
<span className="mr10" style={{ width: '24px' }}>
|
<span className="mr10" style={{ width: '24px' }}>
|
||||||
|
|||||||
@ -1,14 +1,18 @@
|
|||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import Image from 'next/image'
|
import Image from 'next/image'
|
||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
|
import { useRecoilValue } from 'recoil'
|
||||||
|
import { ANGLE_TYPE, currentAngleTypeSelector } from '@/store/canvasAtom'
|
||||||
|
|
||||||
export default function Gable({ pitchRef, offsetRef, widthRef, radioTypeRef }) {
|
export default function Gable({ pitchRef, offsetRef, widthRef, radioTypeRef, pitchText }) {
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
const [type, setType] = useState('1')
|
const [type, setType] = useState('1')
|
||||||
const onChange = (e) => {
|
const onChange = (e) => {
|
||||||
setType(e.target.value)
|
setType(e.target.value)
|
||||||
radioTypeRef.current = e.target.value
|
radioTypeRef.current = e.target.value
|
||||||
}
|
}
|
||||||
|
const currentAngleType = useRecoilValue(currentAngleTypeSelector)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="outline-wrap">
|
<div className="outline-wrap">
|
||||||
@ -57,9 +61,15 @@ export default function Gable({ pitchRef, offsetRef, widthRef, radioTypeRef }) {
|
|||||||
{getMessage('slope')}
|
{getMessage('slope')}
|
||||||
</span>
|
</span>
|
||||||
<div className="input-grid mr5" style={{ width: '100px' }}>
|
<div className="input-grid mr5" style={{ width: '100px' }}>
|
||||||
<input type="text" className="input-origin block" defaultValue={4.5} ref={pitchRef} readOnly={type === '1'} />
|
<input
|
||||||
|
type="text"
|
||||||
|
className="input-origin block"
|
||||||
|
defaultValue={currentAngleType === ANGLE_TYPE.SLOPE ? 4.5 : 20}
|
||||||
|
ref={pitchRef}
|
||||||
|
readOnly={type === '1'}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<span className="thin">寸</span>
|
<span className="thin">{pitchText}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="eaves-keraba-td">
|
<div className="eaves-keraba-td">
|
||||||
|
|||||||
@ -1,24 +1,68 @@
|
|||||||
import WithDraggable from '@/components/common/draggable/withDraggable'
|
import WithDraggable from '@/components/common/draggable/withDraggable'
|
||||||
import { useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import QSelectBox from '@/components/common/select/QSelectBox'
|
import QSelectBox from '@/components/common/select/QSelectBox'
|
||||||
import { useRecoilValue } from 'recoil'
|
import { useRecoilValue } from 'recoil'
|
||||||
import { contextPopupPositionState } from '@/store/popupAtom'
|
import { contextPopupPositionState } from '@/store/popupAtom'
|
||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import { usePopup } from '@/hooks/usePopup'
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
|
|
||||||
const SelectOption01 = [{ name: 'M' }, { name: 'M' }, { name: 'M' }, { name: 'M' }]
|
|
||||||
|
|
||||||
export default function FlowDirectionSetting(props) {
|
export default function FlowDirectionSetting(props) {
|
||||||
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
||||||
const { id, pos = contextPopupPosition } = props
|
const { id, pos = contextPopupPosition, target } = props
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
const { closePopup } = usePopup()
|
const { closePopup } = usePopup()
|
||||||
const [compasDeg, setCompasDeg] = useState(0)
|
const [compasDeg, setCompasDeg] = useState(360)
|
||||||
|
const orientations = [
|
||||||
|
{ name: `${getMessage('commons.south')}`, value: 360 },
|
||||||
|
{ name: `${getMessage('commons.south')}${getMessage('commons.east')}`, value: 315 },
|
||||||
|
{ name: `${getMessage('commons.south')}${getMessage('commons.west')}`, value: 45 },
|
||||||
|
{ name: `${getMessage('commons.east')}`, value: 270 },
|
||||||
|
{ name: `${getMessage('commons.west')}`, value: 90 },
|
||||||
|
{ name: `${getMessage('commons.north')}${getMessage('commons.east')}`, value: 225 },
|
||||||
|
{ name: `${getMessage('commons.north')}${getMessage('commons.west')}`, value: 135 },
|
||||||
|
{ name: `${getMessage('commons.north')}`, value: 180 },
|
||||||
|
]
|
||||||
|
const [selectedOrientation, setSelectedOrientation] = useState(orientations[0])
|
||||||
|
const [type, setType] = useState('0')
|
||||||
|
useEffect(() => {
|
||||||
|
if (target?.angle === 0) {
|
||||||
|
setCompasDeg(360)
|
||||||
|
} else {
|
||||||
|
setCompasDeg(target?.angle ?? 360)
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
useEffect(() => {
|
||||||
|
if (type === '0') {
|
||||||
|
setCompasDeg(selectedOrientation.value)
|
||||||
|
}
|
||||||
|
}, [selectedOrientation])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (type === '1') {
|
||||||
|
if ([15, 345, 360].includes(compasDeg)) {
|
||||||
|
setSelectedOrientation(orientations[0])
|
||||||
|
} else if ([30, 45, 60].includes(compasDeg)) {
|
||||||
|
setSelectedOrientation(orientations[2])
|
||||||
|
} else if ([75, 90, 105].includes(compasDeg)) {
|
||||||
|
setSelectedOrientation(orientations[4])
|
||||||
|
} else if ([120, 135, 150].includes(compasDeg)) {
|
||||||
|
setSelectedOrientation(orientations[6])
|
||||||
|
} else if ([165, 180, 195].includes(compasDeg)) {
|
||||||
|
setSelectedOrientation(orientations[7])
|
||||||
|
} else if ([210, 225, 240].includes(compasDeg)) {
|
||||||
|
setSelectedOrientation(orientations[5])
|
||||||
|
} else if ([255, 270, 285].includes(compasDeg)) {
|
||||||
|
setSelectedOrientation(orientations[3])
|
||||||
|
} else if ([300, 315, 330].includes(compasDeg)) {
|
||||||
|
setSelectedOrientation(orientations[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [compasDeg])
|
||||||
return (
|
return (
|
||||||
<WithDraggable isShow={true} pos={pos}>
|
<WithDraggable isShow={true} pos={pos}>
|
||||||
<div className={`modal-pop-wrap lx`}>
|
<div className={`modal-pop-wrap lx mount`}>
|
||||||
<div className="modal-head">
|
<div className="modal-head">
|
||||||
<h1 className="title">面フローの設定 </h1>
|
<h1 className="title">{getMessage('modal.shape.flow.direction.setting')} </h1>
|
||||||
<button className="modal-close" onClick={() => closePopup(id)}>
|
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||||
닫기
|
닫기
|
||||||
</button>
|
</button>
|
||||||
@ -26,113 +70,59 @@ export default function FlowDirectionSetting(props) {
|
|||||||
<div className="modal-body">
|
<div className="modal-body">
|
||||||
<div className="drawing-flow-wrap">
|
<div className="drawing-flow-wrap">
|
||||||
<div className="discrimination-box">
|
<div className="discrimination-box">
|
||||||
<div className="discrimination-tit mb15">流れ方向の設定</div>
|
<div className="discrimination-tit mb15">{getMessage('modal.flow.direction.setting')}</div>
|
||||||
<div className="guide">流れ方向を選択してください。</div>
|
<div className="guide">{getMessage('modal.flow.direction.setting.info')}</div>
|
||||||
<div className="object-direction-wrap">
|
<div className="object-direction-wrap">
|
||||||
<div className="plane-direction">
|
<div className="plane-direction">
|
||||||
<span className="top">北</span>
|
<span className="top">{getMessage('commons.north')}</span>
|
||||||
<span className="right">ドン</span>
|
|
||||||
<span className="bottom">南</span>
|
|
||||||
<span className="left">立つ</span>
|
|
||||||
<button className="plane-btn up"></button>
|
<button className="plane-btn up"></button>
|
||||||
|
<span className="right">{getMessage('commons.east')}</span>
|
||||||
<button className="plane-btn right"></button>
|
<button className="plane-btn right"></button>
|
||||||
|
<span className="bottom">{getMessage('commons.south')}</span>
|
||||||
<button className="plane-btn down act"></button>
|
<button className="plane-btn down act"></button>
|
||||||
|
<span className="left">{getMessage('commons.west')}</span>
|
||||||
<button className="plane-btn left"></button>
|
<button className="plane-btn left"></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="discrimination-box">
|
<div className="discrimination-box">
|
||||||
<div className="discrimination-tit mb15">方位設定</div>
|
<div className="discrimination-tit mb15">{getMessage('modal.module.basic.setting.orientation.setting')}</div>
|
||||||
<div className="guide">シミュレーション計算の方向を指定します。面が向いている方位を選択してください。</div>
|
<div className="guide">{getMessage('modal.shape.flow.direction.setting.orientation.setting.info')}</div>
|
||||||
<div className="mb-box">
|
<div className="mb-box">
|
||||||
<div className="d-check-radio pop mb15">
|
<div className="d-check-radio pop mb15">
|
||||||
<input type="radio" name="radio01" id="ra01" />
|
<input type="radio" name="radio01" id="ra01" value={0} checked={type === '0'} onChange={(e) => setType(e.target.value)} />
|
||||||
<label htmlFor="ra01">8方位に選ぶ</label>
|
<label htmlFor="ra01">{getMessage('modal.shape.flow.direction.setting.orientation.8')}</label>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid-select ">
|
<div className="grid-select ">
|
||||||
<QSelectBox title={'M'} options={SelectOption01} />
|
<QSelectBox title={''} options={orientations} value={selectedOrientation} onChange={(e) => setSelectedOrientation(e)} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-box">
|
<div className="mb-box">
|
||||||
<div className="d-check-radio pop">
|
<div className="d-check-radio pop">
|
||||||
<input type="radio" name="radio02" id="ra02" />
|
<input type="radio" name="radio01" id="ra02" value={1} checked={type === '1'} onChange={(e) => setType(e.target.value)} />
|
||||||
<label htmlFor="ra02">24方位から選択する (表記は8方位です。)</label>
|
<label htmlFor="ra02">{getMessage('modal.shape.flow.direction.setting.orientation.24')}</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="compas-box">
|
<div className="compas-box">
|
||||||
<div className="compas-box-inner">
|
<div className="compas-box-inner">
|
||||||
<div className={`circle ${compasDeg === 180 ? 'act' : ''}`} onClick={() => setCompasDeg(180)}>
|
{Array.from({ length: 180 / 15 + 1 }).map((dot, index) => (
|
||||||
<i>13</i>
|
<div
|
||||||
|
key={index}
|
||||||
|
className={`circle ${compasDeg === 15 * (12 + index) ? 'act' : ''}`}
|
||||||
|
onClick={() => setCompasDeg(15 * (12 + index))}
|
||||||
|
>
|
||||||
|
<i>{13 - index}</i>
|
||||||
</div>
|
</div>
|
||||||
<div className={`circle ${compasDeg === 195 ? 'act' : ''}`} onClick={() => setCompasDeg(195)}>
|
))}
|
||||||
<i>12</i>
|
{Array.from({ length: 180 / 15 - 1 }).map((dot, index) => (
|
||||||
</div>
|
<div
|
||||||
<div className={`circle ${compasDeg === 210 ? 'act' : ''}`} onClick={() => setCompasDeg(210)}>
|
key={index}
|
||||||
<i>11</i>
|
className={`circle ${compasDeg === 15 * (index + 1) ? 'act' : ''}`}
|
||||||
</div>
|
onClick={() => setCompasDeg(15 * (index + 1))}
|
||||||
<div className={`circle ${compasDeg === 225 ? 'act' : ''}`} onClick={() => setCompasDeg(225)}>
|
>
|
||||||
<i>10</i>
|
<i>{24 - index}</i>
|
||||||
</div>
|
|
||||||
<div className={`circle ${compasDeg === 240 ? 'act' : ''}`} onClick={() => setCompasDeg(240)}>
|
|
||||||
<i>9</i>
|
|
||||||
</div>
|
|
||||||
<div className={`circle ${compasDeg === 255 ? 'act' : ''}`} onClick={() => setCompasDeg(255)}>
|
|
||||||
<i>8</i>
|
|
||||||
</div>
|
|
||||||
<div className={`circle ${compasDeg === 270 ? 'act' : ''}`} onClick={() => setCompasDeg(270)}>
|
|
||||||
<i>7</i>
|
|
||||||
</div>
|
|
||||||
<div className={`circle ${compasDeg === 285 ? 'act' : ''}`} onClick={() => setCompasDeg(285)}>
|
|
||||||
<i>6</i>
|
|
||||||
</div>
|
|
||||||
<div className={`circle ${compasDeg === 300 ? 'act' : ''}`} onClick={() => setCompasDeg(300)}>
|
|
||||||
<i>5</i>
|
|
||||||
</div>
|
|
||||||
<div className={`circle ${compasDeg === 315 ? 'act' : ''}`} onClick={() => setCompasDeg(315)}>
|
|
||||||
<i>4</i>
|
|
||||||
</div>
|
|
||||||
<div className={`circle ${compasDeg === 330 ? 'act' : ''}`} onClick={() => setCompasDeg(330)}>
|
|
||||||
<i>3</i>
|
|
||||||
</div>
|
|
||||||
<div className={`circle ${compasDeg === 345 ? 'act' : ''}`} onClick={() => setCompasDeg(345)}>
|
|
||||||
<i>2</i>
|
|
||||||
</div>
|
|
||||||
<div className={`circle ${compasDeg === 0 ? 'act' : ''}`} onClick={() => setCompasDeg(0)}>
|
|
||||||
<i>1</i>
|
|
||||||
</div>
|
|
||||||
<div className={`circle ${compasDeg === 15 ? 'act' : ''}`} onClick={() => setCompasDeg(15)}>
|
|
||||||
<i>24</i>
|
|
||||||
</div>
|
|
||||||
<div className={`circle ${compasDeg === 30 ? 'act' : ''}`} onClick={() => setCompasDeg(30)}>
|
|
||||||
<i>23</i>
|
|
||||||
</div>
|
|
||||||
<div className={`circle ${compasDeg === 45 ? 'act' : ''}`} onClick={() => setCompasDeg(45)}>
|
|
||||||
<i>22</i>
|
|
||||||
</div>
|
|
||||||
<div className={`circle ${compasDeg === 60 ? 'act' : ''}`} onClick={() => setCompasDeg(60)}>
|
|
||||||
<i>21</i>
|
|
||||||
</div>
|
|
||||||
<div className={`circle ${compasDeg === 75 ? 'act' : ''}`} onClick={() => setCompasDeg(75)}>
|
|
||||||
<i>20</i>
|
|
||||||
</div>
|
|
||||||
<div className={`circle ${compasDeg === 90 ? 'act' : ''}`} onClick={() => setCompasDeg(90)}>
|
|
||||||
<i>19</i>
|
|
||||||
</div>
|
|
||||||
<div className={`circle ${compasDeg === 105 ? 'act' : ''}`} onClick={() => setCompasDeg(105)}>
|
|
||||||
<i>18</i>
|
|
||||||
</div>
|
|
||||||
<div className={`circle ${compasDeg === 120 ? 'act' : ''}`} onClick={() => setCompasDeg(120)}>
|
|
||||||
<i>17</i>
|
|
||||||
</div>
|
|
||||||
<div className={`circle ${compasDeg === 135 ? 'act' : ''}`} onClick={() => setCompasDeg(135)}>
|
|
||||||
<i>16</i>
|
|
||||||
</div>
|
|
||||||
<div className={`circle ${compasDeg === 150 ? 'act' : ''}`} onClick={() => setCompasDeg(150)}>
|
|
||||||
<i>15</i>
|
|
||||||
</div>
|
|
||||||
<div className={`circle ${compasDeg === 165 ? 'act' : ''}`} onClick={() => setCompasDeg(165)}>
|
|
||||||
<i>14</i>
|
|
||||||
</div>
|
</div>
|
||||||
|
))}
|
||||||
<div className="compas">
|
<div className="compas">
|
||||||
<div className="compas-arr" style={{ transform: `rotate(${compasDeg}deg)` }}></div>
|
<div className="compas-arr" style={{ transform: `rotate(${compasDeg}deg)` }}></div>
|
||||||
</div>
|
</div>
|
||||||
@ -141,7 +131,7 @@ export default function FlowDirectionSetting(props) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid-btn-wrap">
|
<div className="grid-btn-wrap">
|
||||||
<button className="btn-frame modal act">保存</button>
|
<button className="btn-frame modal act">{getMessage('modal.common.save')}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -71,7 +71,7 @@ export default function DotLineGrid(props) {
|
|||||||
// 데이터를 최초 한 번만 조회
|
// 데이터를 최초 한 번만 조회
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log('DotLineGrid useEffect 실행')
|
console.log('DotLineGrid useEffect 실행')
|
||||||
// fetchGridSettings()
|
fetchGridSettings()
|
||||||
}, [objectNo])
|
}, [objectNo])
|
||||||
|
|
||||||
const HandleClickClose = () => {
|
const HandleClickClose = () => {
|
||||||
@ -100,9 +100,9 @@ export default function DotLineGrid(props) {
|
|||||||
const patternData = {
|
const patternData = {
|
||||||
INTERVAL: {
|
INTERVAL: {
|
||||||
type: res.gridType,
|
type: res.gridType,
|
||||||
horizontalInterval: res.gridHorizon,
|
horizontalInterval: res.gridHorizon * 10,
|
||||||
verticalInterval: res.gridVertical,
|
verticalInterval: res.gridVertical * 10,
|
||||||
ratioInterval: res.gridRatio,
|
ratioInterval: res.gridRatio * 10,
|
||||||
},
|
},
|
||||||
dimension: res.gridDimen,
|
dimension: res.gridDimen,
|
||||||
DOT: res.dotGridDisplay,
|
DOT: res.dotGridDisplay,
|
||||||
|
|||||||
@ -34,22 +34,24 @@ export default function GridMove(props) {
|
|||||||
<input type="text" className="input-origin" defaultValue={910} />
|
<input type="text" className="input-origin" defaultValue={910} />
|
||||||
</div>
|
</div>
|
||||||
<span>mm</span>
|
<span>mm</span>
|
||||||
|
<div className="direction-move-wrap">
|
||||||
|
<button className="direction up"></button>
|
||||||
|
<button className="direction down act"></button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="input-move-wrap">
|
<div className="input-move-wrap">
|
||||||
<div className="input-move">
|
<div className="input-move">
|
||||||
<input type="text" className="input-origin" defaultValue={910} />
|
<input type="text" className="input-origin" defaultValue={910} />
|
||||||
</div>
|
</div>
|
||||||
<span>mm</span>
|
<span>mm</span>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="direction-move-wrap">
|
<div className="direction-move-wrap">
|
||||||
<button className="direction up"></button>
|
|
||||||
<button className="direction down act"></button>
|
|
||||||
<button className="direction left"></button>
|
<button className="direction left"></button>
|
||||||
<button className="direction right"></button>
|
<button className="direction right"></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div className="grid-btn-wrap">
|
<div className="grid-btn-wrap">
|
||||||
<button className="btn-frame modal act">{getMessage('modal.grid.move.save')}</button>
|
<button className="btn-frame modal act">{getMessage('modal.grid.move.save')}</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
42
src/components/floor-plan/modal/image/ImageSizeSetting.jsx
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
import WithDraggable from '@/components/common/draggable/WithDraggable'
|
||||||
|
import { useState } from 'react'
|
||||||
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
|
import { useRecoilValue } from 'recoil'
|
||||||
|
import { contextPopupPositionState } from '@/store/popupAtom'
|
||||||
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
|
|
||||||
|
export default function ImageSizeSetting(props) {
|
||||||
|
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
||||||
|
const { id, pos = contextPopupPosition, size, setSize } = props
|
||||||
|
const [sizeValue, setSizeValue] = useState(100)
|
||||||
|
const { getMessage } = useMessage()
|
||||||
|
const { closePopup } = usePopup()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<WithDraggable isShow={true} pos={pos}>
|
||||||
|
<div className={`modal-pop-wrap xxxm mount`}>
|
||||||
|
<div className="modal-head">
|
||||||
|
<h1 className="title">{getMessage('modal.image.size.setting')} </h1>
|
||||||
|
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||||
|
닫기
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="modal-body">
|
||||||
|
<div className="range-wrap">
|
||||||
|
<input
|
||||||
|
type="range"
|
||||||
|
id="size"
|
||||||
|
name="volume"
|
||||||
|
min="20"
|
||||||
|
max="200"
|
||||||
|
step={10}
|
||||||
|
value={sizeValue}
|
||||||
|
onChange={(e) => setSizeValue(e.target.value)}
|
||||||
|
/>
|
||||||
|
<label htmlFor="size">{sizeValue}%</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</WithDraggable>
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -3,99 +3,70 @@ import { useRecoilValue } from 'recoil'
|
|||||||
import { contextPopupPositionState } from '@/store/popupAtom'
|
import { contextPopupPositionState } from '@/store/popupAtom'
|
||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import { usePopup } from '@/hooks/usePopup'
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
|
import { useState } from 'react'
|
||||||
|
|
||||||
export default function LinePropertySetting(props) {
|
export default function LinePropertySetting(props) {
|
||||||
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
||||||
const { id, pos = contextPopupPosition } = props
|
const { id, pos = contextPopupPosition } = props
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
const { closePopup } = usePopup()
|
const { closePopup } = usePopup()
|
||||||
|
const properties = [
|
||||||
|
{ name: getMessage('eaves.line'), value: 'eaves' },
|
||||||
|
{ name: getMessage('ridge'), value: 'ridge' },
|
||||||
|
{ name: getMessage('oneside.flow.ridge'), value: 'onesideFlowRidge' },
|
||||||
|
{ name: getMessage('gable'), value: 'gable' },
|
||||||
|
{ name: getMessage('gable.left'), value: 'gableLeft' },
|
||||||
|
{ name: getMessage('gable.right'), value: 'gableRight' },
|
||||||
|
{ name: getMessage('yosemune'), value: 'yosemune' },
|
||||||
|
{ name: getMessage('valley'), value: 'valley' },
|
||||||
|
{ name: getMessage('l.abandon.valley'), value: 'lAbandonValley' },
|
||||||
|
{ name: getMessage('mansard'), value: 'mansard' },
|
||||||
|
{ name: getMessage('wall.merge'), value: 'wallCollection' },
|
||||||
|
{ name: getMessage('wall.merge.type'), value: 'wallCollectionType' },
|
||||||
|
{ name: getMessage('wall.merge.flow'), value: 'wallCollectionFlow' },
|
||||||
|
{ name: getMessage('wall.merge.flow.left'), value: 'wallCollectionFlowLeft' },
|
||||||
|
{ name: getMessage('wall.merge.flow.right'), value: 'wallCollectionFlowRight' },
|
||||||
|
{ name: getMessage('no.setting'), value: 'noSetting' },
|
||||||
|
]
|
||||||
|
const [selectedProperty, setSelectedProperty] = useState(null)
|
||||||
return (
|
return (
|
||||||
<WithDraggable isShow={true} pos={pos}>
|
<WithDraggable isShow={true} pos={pos}>
|
||||||
<div className={`modal-pop-wrap r`}>
|
<div className={`modal-pop-wrap r mount`}>
|
||||||
<div className="modal-head">
|
<div className="modal-head">
|
||||||
<h1 className="title">各辺属性の変更 </h1>
|
<h1 className="title">{getMessage('contextmenu.line.property.edit')} </h1>
|
||||||
<button className="modal-close" onClick={() => closePopup(id)}>
|
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||||
닫기
|
닫기
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="modal-body">
|
<div className="modal-body">
|
||||||
<div className="guide">
|
<div className="guide">
|
||||||
<span className="mb10">属性を変更する辺を選択してください。</span>
|
<span className="mb10">{getMessage('modal.line.property.edit.info')}</span>
|
||||||
<span>選択した値 [龍丸]</span>
|
<span>
|
||||||
|
{getMessage('modal.line.property.edit.selected')} [ {selectedProperty?.name} ]
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="properties-setting-wrap outer">
|
<div className="properties-setting-wrap outer">
|
||||||
<div className="setting-tit">設定</div>
|
<div className="setting-tit">{getMessage('setting')}</div>
|
||||||
<div className="outline-wrap">
|
<div className="outline-wrap">
|
||||||
<div className="radio-grid-wrap">
|
<div className="radio-grid-wrap">
|
||||||
<div className="d-check-radio pop">
|
{properties.map((property, index) => {
|
||||||
<input type="radio" name="radio01" id="ra01" />
|
return (
|
||||||
<label htmlFor="ra01">軒先</label>
|
<div className="d-check-radio pop" key={index}>
|
||||||
</div>
|
<input
|
||||||
<div className="d-check-radio pop">
|
type="radio"
|
||||||
<input type="radio" name="radio01" id="ra02" />
|
name="radio01"
|
||||||
<label htmlFor="ra02">ケラバ</label>
|
id={'ra' + (index + 1 >= 10 ? index + 1 : `0${index + 1}`)}
|
||||||
</div>
|
onChange={(e) => setSelectedProperty(property)}
|
||||||
<div className="d-check-radio pop">
|
/>
|
||||||
<input type="radio" name="radio01" id="ra03" />
|
<label htmlFor={'ra' + (index + 1 > 10 ? index + 1 : `0${index + 1}`)}>{property.name}</label>
|
||||||
<label htmlFor="ra03">龍丸</label>
|
|
||||||
</div>
|
|
||||||
<div className="d-check-radio pop">
|
|
||||||
<input type="radio" name="radio01" id="ra04" />
|
|
||||||
<label htmlFor="ra04">ケラバ左</label>
|
|
||||||
</div>
|
|
||||||
<div className="d-check-radio pop">
|
|
||||||
<input type="radio" name="radio01" id="ra05" />
|
|
||||||
<label htmlFor="ra05">ヨセムネ</label>
|
|
||||||
</div>
|
|
||||||
<div className="d-check-radio pop">
|
|
||||||
<input type="radio" name="radio01" id="ra06" />
|
|
||||||
<label htmlFor="ra06">ケラバ右</label>
|
|
||||||
</div>
|
|
||||||
<div className="d-check-radio pop">
|
|
||||||
<input type="radio" name="radio01" id="ra07" />
|
|
||||||
<label htmlFor="ra07">片側の流れ</label>
|
|
||||||
</div>
|
|
||||||
<div className="d-check-radio pop">
|
|
||||||
<input type="radio" name="radio01" id="ra08" />
|
|
||||||
<label htmlFor="ra08">谷</label>
|
|
||||||
</div>
|
|
||||||
<div className="d-check-radio pop">
|
|
||||||
<input type="radio" name="radio01" id="ra09" />
|
|
||||||
<label htmlFor="ra09">壁取り</label>
|
|
||||||
</div>
|
|
||||||
<div className="d-check-radio pop">
|
|
||||||
<input type="radio" name="radio01" id="ra10" />
|
|
||||||
<label htmlFor="ra10">Lの捨て渓谷</label>
|
|
||||||
</div>
|
|
||||||
<div className="d-check-radio pop">
|
|
||||||
<input type="radio" name="radio01" id="ra11" />
|
|
||||||
<label htmlFor="ra11">壁取り(型)</label>
|
|
||||||
</div>
|
|
||||||
<div className="d-check-radio pop">
|
|
||||||
<input type="radio" name="radio01" id="ra12" />
|
|
||||||
<label htmlFor="ra12">マンサード</label>
|
|
||||||
</div>
|
|
||||||
<div className="d-check-radio pop">
|
|
||||||
<input type="radio" name="radio01" id="ra13" />
|
|
||||||
<label htmlFor="ra13">壁取合(流れ)</label>
|
|
||||||
</div>
|
|
||||||
<div className="d-check-radio pop">
|
|
||||||
<input type="radio" name="radio01" id="ra14" />
|
|
||||||
<label htmlFor="ra14">設定なし</label>
|
|
||||||
</div>
|
|
||||||
<div className="d-check-radio pop">
|
|
||||||
<input type="radio" name="radio01" id="ra15" />
|
|
||||||
<label htmlFor="ra15">壁取合(流れ左)</label>
|
|
||||||
</div>
|
|
||||||
<div className="d-check-radio pop">
|
|
||||||
<input type="radio" name="radio01" id="ra16" />
|
|
||||||
<label htmlFor="ra16">壁取り(流れ右)</label>
|
|
||||||
</div>
|
</div>
|
||||||
|
)
|
||||||
|
})}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid-btn-wrap">
|
<div className="grid-btn-wrap">
|
||||||
<button className="btn-frame modal act">保存</button>
|
<button className="btn-frame modal act">{getMessage('modal.common.save')}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -19,6 +19,7 @@ export default function Angle({ props }) {
|
|||||||
className="input-origin block"
|
className="input-origin block"
|
||||||
value={angle1}
|
value={angle1}
|
||||||
ref={angle1Ref}
|
ref={angle1Ref}
|
||||||
|
onFocus={(e) => (angle1Ref.current.value = '')}
|
||||||
onChange={(e) => onlyNumberWithDotInputChange(e, setAngle1)}
|
onChange={(e) => onlyNumberWithDotInputChange(e, setAngle1)}
|
||||||
placeholder="45"
|
placeholder="45"
|
||||||
/>
|
/>
|
||||||
@ -38,6 +39,7 @@ export default function Angle({ props }) {
|
|||||||
className="input-origin block"
|
className="input-origin block"
|
||||||
value={length1}
|
value={length1}
|
||||||
ref={length1Ref}
|
ref={length1Ref}
|
||||||
|
onFocus={(e) => (length1Ref.current.value = '')}
|
||||||
onChange={(e) => onlyNumberInputChange(e, setLength1)}
|
onChange={(e) => onlyNumberInputChange(e, setLength1)}
|
||||||
placeholder="3000"
|
placeholder="3000"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -35,6 +35,7 @@ export default function Diagonal({ props }) {
|
|||||||
className="input-origin block"
|
className="input-origin block"
|
||||||
value={outerLineDiagonalLength}
|
value={outerLineDiagonalLength}
|
||||||
ref={outerLineDiagonalLengthRef}
|
ref={outerLineDiagonalLengthRef}
|
||||||
|
onFocus={(e) => (outerLineDiagonalLengthRef.current.value = '')}
|
||||||
onChange={(e) => onlyNumberInputChange(e, setOuterLineDiagonalLength)}
|
onChange={(e) => onlyNumberInputChange(e, setOuterLineDiagonalLength)}
|
||||||
placeholder="3000"
|
placeholder="3000"
|
||||||
/>
|
/>
|
||||||
@ -56,6 +57,7 @@ export default function Diagonal({ props }) {
|
|||||||
className="input-origin block"
|
className="input-origin block"
|
||||||
value={length1}
|
value={length1}
|
||||||
ref={length1Ref}
|
ref={length1Ref}
|
||||||
|
onFocus={(e) => (length1Ref.current.value = '')}
|
||||||
onChange={(e) => onlyNumberInputChange(e, setLength1)}
|
onChange={(e) => onlyNumberInputChange(e, setLength1)}
|
||||||
placeholder="3000"
|
placeholder="3000"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -55,6 +55,7 @@ export default function DoublePitch({ props }) {
|
|||||||
className="input-origin block"
|
className="input-origin block"
|
||||||
value={angle1}
|
value={angle1}
|
||||||
ref={angle1Ref}
|
ref={angle1Ref}
|
||||||
|
onFocus={(e) => (angle1Ref.current.value = '')}
|
||||||
onChange={(e) => onlyNumberWithDotInputChange(e, setAngle1)}
|
onChange={(e) => onlyNumberWithDotInputChange(e, setAngle1)}
|
||||||
placeholder="45"
|
placeholder="45"
|
||||||
/>
|
/>
|
||||||
@ -71,6 +72,7 @@ export default function DoublePitch({ props }) {
|
|||||||
className="input-origin block"
|
className="input-origin block"
|
||||||
value={length1}
|
value={length1}
|
||||||
ref={length1Ref}
|
ref={length1Ref}
|
||||||
|
onFocus={(e) => (length1Ref.current.value = '')}
|
||||||
onChange={(e) => onlyNumberInputChange(e, setLength1)}
|
onChange={(e) => onlyNumberInputChange(e, setLength1)}
|
||||||
placeholder="3000"
|
placeholder="3000"
|
||||||
/>
|
/>
|
||||||
@ -128,9 +130,9 @@ export default function DoublePitch({ props }) {
|
|||||||
className="input-origin block"
|
className="input-origin block"
|
||||||
value={angle2}
|
value={angle2}
|
||||||
ref={angle2Ref}
|
ref={angle2Ref}
|
||||||
|
onFocus={(e) => (angle2Ref.current.value = '')}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
onlyNumberWithDotInputChange(e, setAngle2)
|
onlyNumberWithDotInputChange(e, setAngle2)
|
||||||
console.log(getLength2())
|
|
||||||
setLength2(getLength2())
|
setLength2(getLength2())
|
||||||
}}
|
}}
|
||||||
placeholder="45"
|
placeholder="45"
|
||||||
@ -153,6 +155,7 @@ export default function DoublePitch({ props }) {
|
|||||||
className="input-origin block"
|
className="input-origin block"
|
||||||
value={length2}
|
value={length2}
|
||||||
ref={length2Ref}
|
ref={length2Ref}
|
||||||
|
onFocus={(e) => (length2Ref.current.value = '')}
|
||||||
onChange={(e) => onlyNumberInputChange(e, setLength2)}
|
onChange={(e) => onlyNumberInputChange(e, setLength2)}
|
||||||
readOnly={true}
|
readOnly={true}
|
||||||
placeholder="3000"
|
placeholder="3000"
|
||||||
|
|||||||
@ -18,6 +18,7 @@ export default function OuterLineWall({ props }) {
|
|||||||
className="input-origin block"
|
className="input-origin block"
|
||||||
value={length1}
|
value={length1}
|
||||||
ref={length1Ref}
|
ref={length1Ref}
|
||||||
|
onFocus={(e) => (length1Ref.current.value = '')}
|
||||||
onChange={(e) => onlyNumberInputChange(e, setLength1)}
|
onChange={(e) => onlyNumberInputChange(e, setLength1)}
|
||||||
placeholder="3000"
|
placeholder="3000"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -15,6 +15,7 @@ export default function RightAngle({ props }) {
|
|||||||
className="input-origin block"
|
className="input-origin block"
|
||||||
value={length1}
|
value={length1}
|
||||||
ref={length1Ref}
|
ref={length1Ref}
|
||||||
|
onFocus={(e) => (length1Ref.current.value = '')}
|
||||||
onChange={(e) => onlyNumberInputChange(e, setLength1)}
|
onChange={(e) => onlyNumberInputChange(e, setLength1)}
|
||||||
placeholder="3000"
|
placeholder="3000"
|
||||||
/>
|
/>
|
||||||
@ -70,6 +71,7 @@ export default function RightAngle({ props }) {
|
|||||||
className="input-origin block"
|
className="input-origin block"
|
||||||
value={length2}
|
value={length2}
|
||||||
ref={length2Ref}
|
ref={length2Ref}
|
||||||
|
onFocus={(e) => (length2Ref.current.value = '')}
|
||||||
onChange={(e) => onlyNumberInputChange(e, setLength2)}
|
onChange={(e) => onlyNumberInputChange(e, setLength2)}
|
||||||
placeholder="3000"
|
placeholder="3000"
|
||||||
/>
|
/>
|
||||||
|
|||||||
48
src/components/floor-plan/modal/module/CircuitNumberEdit.jsx
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
import WithDraggable from '@/components/common/draggable/withDraggable'
|
||||||
|
import { useRecoilValue } from 'recoil'
|
||||||
|
import { contextPopupPositionState } from '@/store/popupAtom'
|
||||||
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
|
|
||||||
|
export default function CircuitNumberEdit(props) {
|
||||||
|
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
||||||
|
const { id, pos = contextPopupPosition, apply } = props
|
||||||
|
const { closePopup } = usePopup()
|
||||||
|
const { getMessage } = useMessage()
|
||||||
|
const handleApply = () => {
|
||||||
|
if (apply) apply()
|
||||||
|
closePopup(id)
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<WithDraggable isShow={true} pos={pos}>
|
||||||
|
<div className={`modal-pop-wrap xm mount`}>
|
||||||
|
<div className="modal-head">
|
||||||
|
<h1 className="title"> {getMessage('modal.module.circuit.number.edit')}</h1>
|
||||||
|
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||||
|
닫기
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="modal-body">
|
||||||
|
<div className="grid-option-tit"> {getMessage('modal.module.circuit.number.edit.info')}</div>
|
||||||
|
<div className="grid-option-wrap">
|
||||||
|
<div className="grid-option-box">
|
||||||
|
<div className="outline-form">
|
||||||
|
<span className="mr10" style={{ width: 'auto' }}>
|
||||||
|
{getMessage('modal.module.circuit.number')}
|
||||||
|
</span>
|
||||||
|
<div className="input-grid mr5">
|
||||||
|
<input type="text" className="input-origin block" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="grid-btn-wrap">
|
||||||
|
<button className="btn-frame modal act" onClick={handleApply}>
|
||||||
|
{getMessage('modal.common.save')}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</WithDraggable>
|
||||||
|
)
|
||||||
|
}
|
||||||
78
src/components/floor-plan/modal/module/PanelEdit.jsx
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
import WithDraggable from '@/components/common/draggable/WithDraggable'
|
||||||
|
import { useRecoilValue } from 'recoil'
|
||||||
|
import { contextPopupPositionState } from '@/store/popupAtom'
|
||||||
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
|
import { useState } from 'react'
|
||||||
|
|
||||||
|
export default function PanelEdit(props) {
|
||||||
|
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
||||||
|
const { id, pos = contextPopupPosition, type = 'move', apply } = props
|
||||||
|
const { closePopup } = usePopup()
|
||||||
|
const [length, setLength] = useState(0)
|
||||||
|
const [direction, setDirection] = useState('')
|
||||||
|
const { getMessage } = useMessage()
|
||||||
|
|
||||||
|
const handleApply = () => {
|
||||||
|
apply()
|
||||||
|
closePopup(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<WithDraggable isShow={true} pos={pos}>
|
||||||
|
<div className={`modal-pop-wrap xm mount`}>
|
||||||
|
<div className="modal-head">
|
||||||
|
<h1 className="title">{getMessage(type === 'move' ? 'modal.move.setting' : 'modal.copy.setting')} </h1>
|
||||||
|
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||||
|
닫기
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="modal-body">
|
||||||
|
<div className="grid-option-tit">{getMessage(type === 'move' ? 'modal.move.setting.info' : 'modal.copy.setting.info')}</div>
|
||||||
|
<div className="grid-option-wrap">
|
||||||
|
<div className="grid-option-box">
|
||||||
|
<div className="grid-input-form">
|
||||||
|
<span className="mr10">{getMessage('margin')}</span>
|
||||||
|
<div className="input-grid mr5">
|
||||||
|
<input type="text" className="input-origin" defaultValue={0} onClick={(e) => setLength(e.target.value)} />
|
||||||
|
</div>
|
||||||
|
<span>mm</span>
|
||||||
|
</div>
|
||||||
|
<div className="grid-direction">
|
||||||
|
<button
|
||||||
|
className={`direction up ${direction === '↑' ? 'act' : ''}`}
|
||||||
|
onClick={() => {
|
||||||
|
setDirection('↑')
|
||||||
|
}}
|
||||||
|
></button>
|
||||||
|
<button
|
||||||
|
className={`direction down ${direction === '↓' ? 'act' : ''}`}
|
||||||
|
onClick={() => {
|
||||||
|
setDirection('↓')
|
||||||
|
}}
|
||||||
|
></button>
|
||||||
|
<button
|
||||||
|
className={`direction left ${direction === '←' ? 'act' : ''}`}
|
||||||
|
onClick={() => {
|
||||||
|
setDirection('←')
|
||||||
|
}}
|
||||||
|
></button>
|
||||||
|
<button
|
||||||
|
className={`direction right ${direction === '→' ? 'act' : ''}`}
|
||||||
|
onClick={() => {
|
||||||
|
setDirection('→')
|
||||||
|
}}
|
||||||
|
></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="grid-btn-wrap">
|
||||||
|
<button className="btn-frame modal mr5" onClick={handleApply}>
|
||||||
|
{getMessage('modal.common.save')}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</WithDraggable>
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -0,0 +1,95 @@
|
|||||||
|
import WithDraggable from '@/components/common/draggable/WithDraggable'
|
||||||
|
import { useRecoilValue } from 'recoil'
|
||||||
|
import { contextPopupPositionState } from '@/store/popupAtom'
|
||||||
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
|
import { useState } from 'react'
|
||||||
|
import Image from 'next/image'
|
||||||
|
|
||||||
|
export default function ColumnInsert(props) {
|
||||||
|
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
||||||
|
const { id, pos = contextPopupPosition, apply } = props
|
||||||
|
const { closePopup } = usePopup()
|
||||||
|
const [selectedType, setSelectedType] = useState(1)
|
||||||
|
const { getMessage } = useMessage()
|
||||||
|
const handleApply = () => {
|
||||||
|
if (apply) apply()
|
||||||
|
closePopup(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
const HandleRadioChange = (e) => {
|
||||||
|
setSelectedType(Number(e.target.value))
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<WithDraggable isShow={true} pos={pos}>
|
||||||
|
<div className={`modal-pop-wrap r mount`}>
|
||||||
|
<div className="modal-head">
|
||||||
|
<h1 className="title">{getMessage('modal.panel.column.insert')} </h1>
|
||||||
|
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||||
|
닫기
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="modal-body">
|
||||||
|
<div className="properties-setting-wrap">
|
||||||
|
<div className="setting-tit">{getMessage('modal.panel.column.insert.info')}</div>
|
||||||
|
<div className="additional-wrap">
|
||||||
|
<div className="additional-radio-wrap">
|
||||||
|
<div className="d-check-radio pop">
|
||||||
|
<input type="radio" name="radio01" id="ra01" onChange={HandleRadioChange} value={1} checked={selectedType === 1} />
|
||||||
|
<label htmlFor="ra01">{getMessage('modal.panel.column.insert.type.left')}</label>
|
||||||
|
</div>
|
||||||
|
<div className="d-check-radio pop">
|
||||||
|
<input type="radio" name="radio01" id="ra02" onChange={HandleRadioChange} value={2} checked={selectedType === 2} />
|
||||||
|
<label htmlFor="ra02">{getMessage('modal.panel.column.insert.type.right')}</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="additional-img-wrap">
|
||||||
|
{selectedType === 1 && (
|
||||||
|
<Image
|
||||||
|
src="/static/images/canvas/additional-edit01.svg"
|
||||||
|
alt="react"
|
||||||
|
width={0}
|
||||||
|
height={0}
|
||||||
|
style={{ width: 'auto', height: 'auto' }}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{selectedType === 2 && (
|
||||||
|
<Image
|
||||||
|
src="/static/images/canvas/additional-edit02.svg"
|
||||||
|
alt="react"
|
||||||
|
width={0}
|
||||||
|
height={0}
|
||||||
|
style={{ width: 'auto', height: 'auto' }}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="properties-setting-wrap">
|
||||||
|
<div className="setting-tit">{getMessage('legend')}</div>
|
||||||
|
<div className="module-table-box">
|
||||||
|
<div className="module-table-inner">
|
||||||
|
<div className="additional-color-wrap">
|
||||||
|
<div className="additional-color-box">
|
||||||
|
<span className="additional-color pink"></span>
|
||||||
|
<span className="normal-font">{getMessage('modal.panel.select.column')}</span>
|
||||||
|
</div>
|
||||||
|
<div className="additional-color-box">
|
||||||
|
<span className="additional-color white"></span>
|
||||||
|
<span className="normal-font">{getMessage('modal.panel.insert.column')}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="grid-btn-wrap">
|
||||||
|
<button className="btn-frame modal act" onClick={handleApply}>
|
||||||
|
{getMessage('modal.common.save')}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</WithDraggable>
|
||||||
|
)
|
||||||
|
}
|
||||||
118
src/components/floor-plan/modal/module/column/ColumnRemove.jsx
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
import WithDraggable from '@/components/common/draggable/WithDraggable'
|
||||||
|
import { useRecoilValue } from 'recoil'
|
||||||
|
import { contextPopupPositionState } from '@/store/popupAtom'
|
||||||
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
|
import { useState } from 'react'
|
||||||
|
import Image from 'next/image'
|
||||||
|
|
||||||
|
export default function ColumnRemove(props) {
|
||||||
|
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
||||||
|
const { id, pos = contextPopupPosition, apply } = props
|
||||||
|
const { closePopup } = usePopup()
|
||||||
|
const [selectedType, setSelectedType] = useState(1)
|
||||||
|
const { getMessage } = useMessage()
|
||||||
|
const types = [
|
||||||
|
{ name: getMessage('modal.panel.column.remove.type.left'), value: 1 },
|
||||||
|
{ name: getMessage('modal.panel.column.remove.type.right'), value: 2 },
|
||||||
|
{ name: getMessage('modal.panel.column.remove.type.side'), value: 3 },
|
||||||
|
{ name: getMessage('modal.panel.column.remove.type.none'), value: 4 },
|
||||||
|
]
|
||||||
|
const handleApply = () => {
|
||||||
|
if (apply) apply()
|
||||||
|
closePopup(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<WithDraggable isShow={true} pos={pos}>
|
||||||
|
<div className={`modal-pop-wrap r mount`}>
|
||||||
|
<div className="modal-head">
|
||||||
|
<h1 className="title">{getMessage('modal.panel.column.remove')} </h1>
|
||||||
|
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||||
|
닫기
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="modal-body">
|
||||||
|
<div className="properties-setting-wrap">
|
||||||
|
<div className="setting-tit">{getMessage('modal.panel.column.remove.info')}</div>
|
||||||
|
<div className="additional-wrap">
|
||||||
|
<div className="additional-radio-wrap">
|
||||||
|
{types.map((type, index) => {
|
||||||
|
return (
|
||||||
|
<div className="d-check-radio pop">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="radio01"
|
||||||
|
id={`ra0${index + 1}`}
|
||||||
|
onClick={(e) => setSelectedType(Number(e.target.value))}
|
||||||
|
value={type.value}
|
||||||
|
checked={selectedType === type.value}
|
||||||
|
/>
|
||||||
|
<label htmlFor={`ra0${index + 1}`}>{type.name}</label>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
<div className="additional-img-wrap">
|
||||||
|
{selectedType === 1 && (
|
||||||
|
<Image
|
||||||
|
src="/static/images/canvas/additional_del01.svg"
|
||||||
|
alt="react"
|
||||||
|
width={0}
|
||||||
|
height={0}
|
||||||
|
style={{ width: 'auto', height: 'auto' }}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{selectedType === 2 && (
|
||||||
|
<Image
|
||||||
|
src="/static/images/canvas/additional_del02.svg"
|
||||||
|
alt="react"
|
||||||
|
width={0}
|
||||||
|
height={0}
|
||||||
|
style={{ width: 'auto', height: 'auto' }}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{selectedType === 3 && (
|
||||||
|
<Image
|
||||||
|
src="/static/images/canvas/additional_del03.svg"
|
||||||
|
alt="react"
|
||||||
|
width={0}
|
||||||
|
height={0}
|
||||||
|
style={{ width: 'auto', height: 'auto' }}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{selectedType === 4 && (
|
||||||
|
<Image
|
||||||
|
src="/static/images/canvas/additional_del04.svg"
|
||||||
|
alt="react"
|
||||||
|
width={0}
|
||||||
|
height={0}
|
||||||
|
style={{ width: 'auto', height: 'auto' }}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="properties-setting-wrap">
|
||||||
|
<div className="setting-tit">{getMessage('legend')}</div>
|
||||||
|
<div className="module-table-box">
|
||||||
|
<div className="module-table-inner">
|
||||||
|
<div className="additional-color-wrap">
|
||||||
|
<div className="additional-color-box">
|
||||||
|
<span className="additional-color pink"></span>
|
||||||
|
<span className="normal-font">{getMessage('modal.panel.select.column')}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="grid-btn-wrap">
|
||||||
|
<button className="btn-frame modal act" onClick={handleApply}>
|
||||||
|
{getMessage('modal.common.save')}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</WithDraggable>
|
||||||
|
)
|
||||||
|
}
|
||||||
95
src/components/floor-plan/modal/module/row/RowInsert.jsx
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
import WithDraggable from '@/components/common/draggable/withDraggable'
|
||||||
|
import Image from 'next/image'
|
||||||
|
import { useState } from 'react'
|
||||||
|
import { useRecoilValue } from 'recoil'
|
||||||
|
import { contextPopupPositionState } from '@/store/popupAtom'
|
||||||
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
|
|
||||||
|
export default function RowInsert(props) {
|
||||||
|
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
||||||
|
const { id, pos = contextPopupPosition, apply } = props
|
||||||
|
const { closePopup } = usePopup()
|
||||||
|
const [selectedType, setSelectedType] = useState(1)
|
||||||
|
const { getMessage } = useMessage()
|
||||||
|
const handleApply = () => {
|
||||||
|
if (apply) apply()
|
||||||
|
closePopup(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
const HandleRadioChange = (e) => {
|
||||||
|
setSelectedType(Number(e.target.value))
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<WithDraggable isShow={true} pos={pos}>
|
||||||
|
<div className={`modal-pop-wrap r mount`}>
|
||||||
|
<div className="modal-head">
|
||||||
|
<h1 className="title">{getMessage('modal.row.insert')} </h1>
|
||||||
|
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||||
|
닫기
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="modal-body">
|
||||||
|
<div className="properties-setting-wrap">
|
||||||
|
<div className="setting-tit">{getMessage('modal.row.insert.info')}</div>
|
||||||
|
<div className="additional-wrap">
|
||||||
|
<div className="additional-radio-wrap">
|
||||||
|
<div className="d-check-radio pop">
|
||||||
|
<input type="radio" name="radio01" id="ra01" onChange={HandleRadioChange} value={1} checked={selectedType === 1} />
|
||||||
|
<label htmlFor="ra01">{getMessage('modal.row.insert.type.up')}</label>
|
||||||
|
</div>
|
||||||
|
<div className="d-check-radio pop">
|
||||||
|
<input type="radio" name="radio01" id="ra02" onChange={HandleRadioChange} value={2} checked={selectedType === 2} />
|
||||||
|
<label htmlFor="ra02">{getMessage('modal.row.insert.type.down')}</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="additional-img-wrap">
|
||||||
|
{selectedType === 1 && (
|
||||||
|
<Image
|
||||||
|
src="/static/images/canvas/additional_bundle-edit01.svg"
|
||||||
|
alt="react"
|
||||||
|
width={0}
|
||||||
|
height={0}
|
||||||
|
style={{ width: 'auto', height: 'auto' }}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{selectedType === 2 && (
|
||||||
|
<Image
|
||||||
|
src="/static/images/canvas/additional_bundle-edit02.svg"
|
||||||
|
alt="react"
|
||||||
|
width={0}
|
||||||
|
height={0}
|
||||||
|
style={{ width: 'auto', height: 'auto' }}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="properties-setting-wrap">
|
||||||
|
<div className="setting-tit">{getMessage('legend')}</div>
|
||||||
|
<div className="module-table-box">
|
||||||
|
<div className="module-table-inner">
|
||||||
|
<div className="additional-color-wrap">
|
||||||
|
<div className="additional-color-box">
|
||||||
|
<span className="additional-color pink"></span>
|
||||||
|
<span className="normal-font">{getMessage('modal.panel.select.row')}</span>
|
||||||
|
</div>
|
||||||
|
<div className="additional-color-box">
|
||||||
|
<span className="additional-color white"></span>
|
||||||
|
<span className="normal-font">{getMessage('modal.panel.insert.row')}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="grid-btn-wrap">
|
||||||
|
<button className="btn-frame modal act" onClick={handleApply}>
|
||||||
|
{getMessage('modal.common.save')}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</WithDraggable>
|
||||||
|
)
|
||||||
|
}
|
||||||
118
src/components/floor-plan/modal/module/row/RowRemove.jsx
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
import WithDraggable from '@/components/common/draggable/withDraggable'
|
||||||
|
import Image from 'next/image'
|
||||||
|
import { useState } from 'react'
|
||||||
|
import { useRecoilValue } from 'recoil'
|
||||||
|
import { contextPopupPositionState } from '@/store/popupAtom'
|
||||||
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
|
|
||||||
|
export default function RowRemove(props) {
|
||||||
|
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
||||||
|
const { id, pos = contextPopupPosition, apply } = props
|
||||||
|
const { closePopup } = usePopup()
|
||||||
|
const [selectedType, setSelectedType] = useState(1)
|
||||||
|
const { getMessage } = useMessage()
|
||||||
|
const types = [
|
||||||
|
{ name: getMessage('modal.row.remove.type.up'), value: 1 },
|
||||||
|
{ name: getMessage('modal.row.remove.type.down'), value: 2 },
|
||||||
|
{ name: getMessage('modal.row.remove.type.side'), value: 3 },
|
||||||
|
{ name: getMessage('modal.row.remove.type.none'), value: 4 },
|
||||||
|
]
|
||||||
|
const handleApply = () => {
|
||||||
|
if (apply) apply()
|
||||||
|
closePopup(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<WithDraggable isShow={true} pos={pos}>
|
||||||
|
<div className={`modal-pop-wrap r mount`}>
|
||||||
|
<div className="modal-head">
|
||||||
|
<h1 className="title">{getMessage('modal.row.remove')}</h1>
|
||||||
|
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||||
|
닫기
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="modal-body">
|
||||||
|
<div className="properties-setting-wrap">
|
||||||
|
<div className="setting-tit">{getMessage('modal.row.remove.info')}</div>
|
||||||
|
<div className="additional-wrap">
|
||||||
|
<div className="additional-radio-wrap">
|
||||||
|
{types.map((type, index) => {
|
||||||
|
return (
|
||||||
|
<div className="d-check-radio pop">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="radio01"
|
||||||
|
id={`ra0${index + 1}`}
|
||||||
|
onClick={() => setSelectedType(Number(e.target.value))}
|
||||||
|
value={type.value}
|
||||||
|
checked={selectedType === type.value}
|
||||||
|
/>
|
||||||
|
<label htmlFor="ra01">{getMessage(type.name)}</label>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
<div className="additional-img-wrap">
|
||||||
|
{selectedType === 1 && (
|
||||||
|
<Image
|
||||||
|
src="/static/images/canvas/additional_bundle-del01.svg"
|
||||||
|
alt="react"
|
||||||
|
width={0}
|
||||||
|
height={0}
|
||||||
|
style={{ width: 'auto', height: 'auto' }}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{selectedType === 2 && (
|
||||||
|
<Image
|
||||||
|
src="/static/images/canvas/additional_bundle-del02.svg"
|
||||||
|
alt="react"
|
||||||
|
width={0}
|
||||||
|
height={0}
|
||||||
|
style={{ width: 'auto', height: 'auto' }}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{selectedType === 3 && (
|
||||||
|
<Image
|
||||||
|
src="/static/images/canvas/additional_bundle-del03.svg"
|
||||||
|
alt="react"
|
||||||
|
width={0}
|
||||||
|
height={0}
|
||||||
|
style={{ width: 'auto', height: 'auto' }}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{selectedType === 4 && (
|
||||||
|
<Image
|
||||||
|
src="/static/images/canvas/additional_bundle-del04.svg"
|
||||||
|
alt="react"
|
||||||
|
width={0}
|
||||||
|
height={0}
|
||||||
|
style={{ width: 'auto', height: 'auto' }}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="properties-setting-wrap">
|
||||||
|
<div className="setting-tit">{getMessage('legend')}</div>
|
||||||
|
<div className="module-table-box">
|
||||||
|
<div className="module-table-inner">
|
||||||
|
<div className="additional-color-wrap">
|
||||||
|
<div className="additional-color-box">
|
||||||
|
<span className="additional-color pink"></span>
|
||||||
|
<span className="normal-font">{getMessage('modal.panel.select.row')}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="grid-btn-wrap">
|
||||||
|
<button className="btn-frame modal act" onClick={handleApply}>
|
||||||
|
{getMessage('modal.common.save')}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</WithDraggable>
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -4,15 +4,18 @@ import { useState } from 'react'
|
|||||||
import FlowLine from '@/components/floor-plan/modal/movement/type/FlowLine'
|
import FlowLine from '@/components/floor-plan/modal/movement/type/FlowLine'
|
||||||
import Updown from '@/components/floor-plan/modal/movement/type/Updown'
|
import Updown from '@/components/floor-plan/modal/movement/type/Updown'
|
||||||
import { usePopup } from '@/hooks/usePopup'
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
|
import { useMovementSetting } from '@/hooks/roofcover/useMovementSetting'
|
||||||
|
|
||||||
export default function MovementSetting({ id, pos = { x: 50, y: 230 } }) {
|
export default function MovementSetting({ id, pos = { x: 50, y: 230 } }) {
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
const { closePopup } = usePopup()
|
const { TYPE, closePopup, buttonType, type, setType, FLOW_LINE_REF, UP_DOWN_REF, handleSave } = useMovementSetting(id)
|
||||||
const [buttonAct, setButtonAct] = useState(1)
|
|
||||||
const buttonMenu = [
|
const flowLineProps = {
|
||||||
{ id: 1, name: getMessage('modal.movement.flow.line.move') },
|
FLOW_LINE_REF,
|
||||||
{ id: 2, name: getMessage('modal.movement.flow.line.updown') },
|
}
|
||||||
]
|
const updownProps = {
|
||||||
|
UP_DOWN_REF,
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<WithDraggable isShow={true} pos={pos}>
|
<WithDraggable isShow={true} pos={pos}>
|
||||||
@ -25,19 +28,21 @@ export default function MovementSetting({ id, pos = { x: 50, y: 230 } }) {
|
|||||||
</div>
|
</div>
|
||||||
<div className="modal-body">
|
<div className="modal-body">
|
||||||
<div className="modal-btn-wrap">
|
<div className="modal-btn-wrap">
|
||||||
{buttonMenu.map((item) => (
|
{buttonType.map((item) => (
|
||||||
<button key={item.id} className={`btn-frame modal ${buttonAct === item.id ? 'act' : ''}`} onClick={() => setButtonAct(item.id)}>
|
<button key={item.id} className={`btn-frame modal ${type === item.type ? 'act' : ''}`} onClick={() => setType(item.type)}>
|
||||||
{item.name}
|
{item.name}
|
||||||
</button>
|
</button>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
<div className="properties-setting-wrap outer">
|
<div className="properties-setting-wrap outer">
|
||||||
<div className="setting-tit">{getMessage('setting')}</div>
|
<div className="setting-tit">{getMessage('setting')}</div>
|
||||||
{buttonAct === 1 && <FlowLine />}
|
{type === TYPE.FLOW_LINE && <FlowLine {...flowLineProps} />}
|
||||||
{buttonAct === 2 && <Updown />}
|
{type === TYPE.UP_DOWN && <Updown {...updownProps} />}
|
||||||
</div>
|
</div>
|
||||||
<div className="grid-btn-wrap">
|
<div className="grid-btn-wrap">
|
||||||
<button className="btn-frame modal act">{getMessage('modal.common.save')}</button>
|
<button className="btn-frame modal act" onClick={handleSave}>
|
||||||
|
{getMessage('modal.common.save')}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,7 +1,25 @@
|
|||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
|
import { useEffect, useState } from 'react'
|
||||||
|
import { useEvent } from '@/hooks/useEvent'
|
||||||
|
|
||||||
export default function FlowLine({}) {
|
const FLOW_LINE_TYPE = {
|
||||||
|
DOWN_LEFT: 'downLeft',
|
||||||
|
UP_RIGHT: 'upRight',
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function FlowLine({ FLOW_LINE_REF }) {
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
|
const [type, setType] = useState(FLOW_LINE_TYPE.DOWN_LEFT)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (type === FLOW_LINE_TYPE.DOWN_LEFT) {
|
||||||
|
FLOW_LINE_REF.UP_RIGHT_INPUT_REF.current.value = ''
|
||||||
|
FLOW_LINE_REF.DOWN_LEFT_INPUT_REF.current.focus()
|
||||||
|
} else {
|
||||||
|
FLOW_LINE_REF.DOWN_LEFT_INPUT_REF.current.value = ''
|
||||||
|
FLOW_LINE_REF.UP_RIGHT_INPUT_REF.current.focus()
|
||||||
|
}
|
||||||
|
}, [type])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -11,14 +29,23 @@ export default function FlowLine({}) {
|
|||||||
<div className="eaves-keraba-item">
|
<div className="eaves-keraba-item">
|
||||||
<div className="eaves-keraba-th">
|
<div className="eaves-keraba-th">
|
||||||
<div className="d-check-radio pop">
|
<div className="d-check-radio pop">
|
||||||
<input type="radio" name="radio01" id="ra01" />
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="radio01"
|
||||||
|
id="ra01"
|
||||||
|
defaultChecked={true}
|
||||||
|
ref={FLOW_LINE_REF.DOWN_LEFT_RADIO_REF}
|
||||||
|
onChange={() => {
|
||||||
|
setType(FLOW_LINE_TYPE.DOWN_LEFT)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
<label htmlFor="ra01">{getMessage('modal.movement.flow.line.bottom.left')}</label>
|
<label htmlFor="ra01">{getMessage('modal.movement.flow.line.bottom.left')}</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="eaves-keraba-td">
|
<div className="eaves-keraba-td">
|
||||||
<div className="outline-form">
|
<div className="outline-form">
|
||||||
<div className="input-grid mr5" style={{ width: '100px' }}>
|
<div className="input-grid mr5" style={{ width: '100px' }}>
|
||||||
<input type="text" className="input-origin block" defaultValue={100} />
|
<input type="text" className="input-origin block" readOnly={true} ref={FLOW_LINE_REF.DOWN_LEFT_INPUT_REF} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -26,14 +53,27 @@ export default function FlowLine({}) {
|
|||||||
<div className="eaves-keraba-item">
|
<div className="eaves-keraba-item">
|
||||||
<div className="eaves-keraba-th">
|
<div className="eaves-keraba-th">
|
||||||
<div className="d-check-radio pop">
|
<div className="d-check-radio pop">
|
||||||
<input type="radio" name="radio01" id="ra02" />
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="radio01"
|
||||||
|
id="ra02"
|
||||||
|
ref={FLOW_LINE_REF.UP_RIGHT_RADIO_REF}
|
||||||
|
onChange={() => {
|
||||||
|
setType(FLOW_LINE_TYPE.UP_RIGHT)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
<label htmlFor="ra02">{getMessage('modal.movement.flow.line.top.right')}</label>
|
<label htmlFor="ra02">{getMessage('modal.movement.flow.line.top.right')}</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="eaves-keraba-td">
|
<div className="eaves-keraba-td">
|
||||||
<div className="outline-form">
|
<div className="outline-form">
|
||||||
<div className="input-grid mr5" style={{ width: '100px' }}>
|
<div className="input-grid mr5" style={{ width: '100px' }}>
|
||||||
<input type="text" className="input-origin block" defaultValue={100} />
|
<input
|
||||||
|
type="text"
|
||||||
|
className="input-origin block"
|
||||||
|
readOnly={type !== FLOW_LINE_TYPE.UP_RIGHT}
|
||||||
|
ref={FLOW_LINE_REF.UP_RIGHT_INPUT_REF}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<span className="thin">mm</span>
|
<span className="thin">mm</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,7 +1,28 @@
|
|||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
|
import { useEffect, useState } from 'react'
|
||||||
|
import { useEvent } from '@/hooks/useEvent'
|
||||||
|
import { canvasState } from '@/store/canvasAtom'
|
||||||
|
import { useRecoilValue } from 'recoil'
|
||||||
|
|
||||||
export default function Updown({}) {
|
const UP_DOWN_TYPE = {
|
||||||
|
UP: 'up',
|
||||||
|
DOWN: 'down',
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function Updown({ UP_DOWN_REF }) {
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
|
const [type, setType] = useState(UP_DOWN_TYPE.UP)
|
||||||
|
const canvas = useRecoilValue(canvasState)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (type === UP_DOWN_TYPE.UP) {
|
||||||
|
UP_DOWN_REF.DOWN_INPUT_REF.current.value = ''
|
||||||
|
UP_DOWN_REF.UP_INPUT_REF.current.focus()
|
||||||
|
} else {
|
||||||
|
UP_DOWN_REF.UP_INPUT_REF.current.value = ''
|
||||||
|
UP_DOWN_REF.DOWN_INPUT_REF.current.focus()
|
||||||
|
}
|
||||||
|
}, [type])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -11,14 +32,23 @@ export default function Updown({}) {
|
|||||||
<div className="eaves-keraba-item">
|
<div className="eaves-keraba-item">
|
||||||
<div className="eaves-keraba-th">
|
<div className="eaves-keraba-th">
|
||||||
<div className="d-check-radio pop">
|
<div className="d-check-radio pop">
|
||||||
<input type="radio" name="radio01" id="ra01" />
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="radio01"
|
||||||
|
id="ra01"
|
||||||
|
ref={UP_DOWN_REF.UP_RADIO_REF}
|
||||||
|
defaultChecked={true}
|
||||||
|
onChange={() => {
|
||||||
|
setType(UP_DOWN_TYPE.UP)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
<label htmlFor="ra01">{getMessage('modal.movement.flow.line.updown.up')}</label>
|
<label htmlFor="ra01">{getMessage('modal.movement.flow.line.updown.up')}</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="eaves-keraba-td">
|
<div className="eaves-keraba-td">
|
||||||
<div className="outline-form">
|
<div className="outline-form">
|
||||||
<div className="input-grid mr5" style={{ width: '100px' }}>
|
<div className="input-grid mr5" style={{ width: '100px' }}>
|
||||||
<input type="text" className="input-origin block" defaultValue={100} />
|
<input type="text" className="input-origin block" readOnly={true} ref={UP_DOWN_REF.UP_INPUT_REF} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -26,14 +56,22 @@ export default function Updown({}) {
|
|||||||
<div className="eaves-keraba-item">
|
<div className="eaves-keraba-item">
|
||||||
<div className="eaves-keraba-th">
|
<div className="eaves-keraba-th">
|
||||||
<div className="d-check-radio pop">
|
<div className="d-check-radio pop">
|
||||||
<input type="radio" name="radio01" id="ra02" />
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="radio01"
|
||||||
|
id="ra02"
|
||||||
|
ref={UP_DOWN_REF.DOWN_RADIO_REF}
|
||||||
|
onChange={() => {
|
||||||
|
setType(UP_DOWN_TYPE.DOWN)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
<label htmlFor="ra02">{getMessage('modal.movement.flow.line.updown.down')}</label>
|
<label htmlFor="ra02">{getMessage('modal.movement.flow.line.updown.down')}</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="eaves-keraba-td">
|
<div className="eaves-keraba-td">
|
||||||
<div className="outline-form">
|
<div className="outline-form">
|
||||||
<div className="input-grid mr5" style={{ width: '100px' }}>
|
<div className="input-grid mr5" style={{ width: '100px' }}>
|
||||||
<input type="text" className="input-origin block" defaultValue={100} />
|
<input type="text" className="input-origin block" readOnly={type !== UP_DOWN_TYPE.DOWN} ref={UP_DOWN_REF.DOWN_INPUT_REF} />
|
||||||
</div>
|
</div>
|
||||||
<span className="thin">mm</span>
|
<span className="thin">mm</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -3,50 +3,79 @@ import WithDraggable from '@/components/common/draggable/WithDraggable'
|
|||||||
import { useRecoilValue } from 'recoil'
|
import { useRecoilValue } from 'recoil'
|
||||||
import { contextPopupPositionState } from '@/store/popupAtom'
|
import { contextPopupPositionState } from '@/store/popupAtom'
|
||||||
import { usePopup } from '@/hooks/usePopup'
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
|
import { useState } from 'react'
|
||||||
|
|
||||||
export default function DormerOffset(props) {
|
export default function DormerOffset(props) {
|
||||||
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
||||||
const { id, pos = contextPopupPosition } = props
|
const { id, pos = contextPopupPosition } = props
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
const { closePopup } = usePopup()
|
const { closePopup } = usePopup()
|
||||||
|
const [arrow1, setArrow1] = useState(null)
|
||||||
|
const [arrow2, setArrow2] = useState(null)
|
||||||
return (
|
return (
|
||||||
<WithDraggable isShow={true} pos={pos}>
|
<WithDraggable isShow={true} pos={pos}>
|
||||||
<div className={`modal-pop-wrap xm`}>
|
<div className={`modal-pop-wrap xm mount`}>
|
||||||
<div className="modal-head">
|
<div className="modal-head">
|
||||||
<h1 className="title">도머 오프셋 </h1>
|
<h1 className="title">{getMessage('contextmenu.dormer.offset')}</h1>
|
||||||
<button className="modal-close" onClick={() => closePopup(id)}>
|
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||||
닫기
|
닫기
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="modal-body">
|
<div className="modal-body">
|
||||||
<div className="grid-option-tit">移動する方向を入力してください</div>
|
<div className="grid-option-tit">{getMessage('modal.dormer.offset.info')}</div>
|
||||||
<div className="grid-option-wrap">
|
<div className="grid-option-wrap">
|
||||||
<div className="grid-option-box">
|
<div className="grid-option-box">
|
||||||
<div className="move-form">
|
<div className="move-form">
|
||||||
<p className="mb5">長さ</p>
|
<p className="mb5">{getMessage('length')}</p>
|
||||||
<div className="input-move-wrap mb5">
|
<div className="input-move-wrap mb5">
|
||||||
<div className="input-move">
|
<div className="input-move">
|
||||||
<input type="text" className="input-origin" defaultValue={910} />
|
<input type="text" className="input-origin" defaultValue={0} />
|
||||||
</div>
|
</div>
|
||||||
<span>mm</span>
|
<span>mm</span>
|
||||||
|
<div className="direction-move-wrap">
|
||||||
|
<button
|
||||||
|
className={`direction up ${arrow1 === '↑' ? 'act' : ''}`}
|
||||||
|
onClick={() => {
|
||||||
|
setArrow1('↑')
|
||||||
|
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowUp' }))
|
||||||
|
}}
|
||||||
|
></button>
|
||||||
|
<button
|
||||||
|
className={`direction down ${arrow1 === '↓' ? 'act' : ''}`}
|
||||||
|
onClick={() => {
|
||||||
|
setArrow1('↓')
|
||||||
|
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown' }))
|
||||||
|
}}
|
||||||
|
></button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="input-move-wrap">
|
<div className="input-move-wrap">
|
||||||
<div className="input-move">
|
<div className="input-move">
|
||||||
<input type="text" className="input-origin" defaultValue={910} />
|
<input type="text" className="input-origin" defaultValue={0} />
|
||||||
</div>
|
</div>
|
||||||
<span>mm</span>
|
<span>mm</span>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="direction-move-wrap">
|
<div className="direction-move-wrap">
|
||||||
<button className="direction up"></button>
|
<button
|
||||||
<button className="direction down act"></button>
|
className={`direction left ${arrow2 === '←' ? 'act' : ''}`}
|
||||||
<button className="direction left"></button>
|
onClick={() => {
|
||||||
<button className="direction right"></button>
|
setArrow2('←')
|
||||||
|
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowLeft' }))
|
||||||
|
}}
|
||||||
|
></button>
|
||||||
|
<button
|
||||||
|
className={`direction right ${arrow2 === '→' ? 'act' : ''}`}
|
||||||
|
onClick={() => {
|
||||||
|
setArrow2('→')
|
||||||
|
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowRight' }))
|
||||||
|
}}
|
||||||
|
></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid-btn-wrap">
|
<div className="grid-btn-wrap">
|
||||||
<button className="btn-frame modal act">保存</button>
|
<button className="btn-frame modal act">{getMessage('modal.common.save')}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -19,7 +19,8 @@ export default function ObjectSetting({ id, pos = { x: 50, y: 230 } }) {
|
|||||||
const canvas = useRecoilValue(canvasState)
|
const canvas = useRecoilValue(canvasState)
|
||||||
const [buttonAct, setButtonAct] = useState(1)
|
const [buttonAct, setButtonAct] = useState(1)
|
||||||
const { swalFire } = useSwal()
|
const { swalFire } = useSwal()
|
||||||
const { applyOpeningAndShadow, applyDormers } = useObjectBatch()
|
const [isHidden, setIsHidden] = useState(false)
|
||||||
|
const { applyOpeningAndShadow, applyDormers } = useObjectBatch({ isHidden, setIsHidden })
|
||||||
const { closePopup } = usePopup()
|
const { closePopup } = usePopup()
|
||||||
|
|
||||||
const surfaceShapePolygons = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF)
|
const surfaceShapePolygons = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF)
|
||||||
@ -63,6 +64,7 @@ export default function ObjectSetting({ id, pos = { x: 50, y: 230 } }) {
|
|||||||
} else {
|
} else {
|
||||||
applyDormers(dormerPlacement, buttonAct, surfaceShapePolygons)
|
applyDormers(dormerPlacement, buttonAct, surfaceShapePolygons)
|
||||||
}
|
}
|
||||||
|
setIsHidden(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
const buttonMenu = [
|
const buttonMenu = [
|
||||||
@ -71,9 +73,10 @@ export default function ObjectSetting({ id, pos = { x: 50, y: 230 } }) {
|
|||||||
{ id: 3, name: getMessage('modal.object.setting.type.triangle.dormer') },
|
{ id: 3, name: getMessage('modal.object.setting.type.triangle.dormer') },
|
||||||
{ id: 4, name: getMessage('modal.object.setting.type.pentagon.dormer') },
|
{ id: 4, name: getMessage('modal.object.setting.type.pentagon.dormer') },
|
||||||
]
|
]
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<WithDraggable isShow={true} pos={pos}>
|
<WithDraggable isShow={true} pos={pos}>
|
||||||
<div className={`modal-pop-wrap lrr`}>
|
<div className={`modal-pop-wrap lrr`} style={{ visibility: isHidden ? 'hidden' : 'visible' }}>
|
||||||
<div className="modal-head">
|
<div className="modal-head">
|
||||||
<h1 className="title">{getMessage('plan.menu.placement.surface.object')} </h1>
|
<h1 className="title">{getMessage('plan.menu.placement.surface.object')} </h1>
|
||||||
<button className="modal-close" onClick={() => closePopup(id)}>
|
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||||
|
|||||||
@ -22,9 +22,9 @@ export default function RoofMaterialSetting(props) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<WithDraggable isShow={true} pos={pos}>
|
<WithDraggable isShow={true} pos={pos}>
|
||||||
<div className={`modal-pop-wrap xxxm`}>
|
<div className={`modal-pop-wrap xxxm mount`}>
|
||||||
<div className="modal-head">
|
<div className="modal-head">
|
||||||
<h1 className="title">変更 </h1>
|
<h1 className="title">{getMessage('modal.roof.material.edit')} </h1>
|
||||||
<button className="modal-close" onClick={() => closePopup(id)}>
|
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||||
닫기
|
닫기
|
||||||
</button>
|
</button>
|
||||||
@ -36,7 +36,7 @@ export default function RoofMaterialSetting(props) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid-btn-wrap">
|
<div className="grid-btn-wrap">
|
||||||
<button className="btn-frame modal act">ストレージ</button>
|
<button className="btn-frame modal act">{getMessage('modal.common.save')}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -2,25 +2,42 @@
|
|||||||
|
|
||||||
import { useRecoilValue } from 'recoil'
|
import { useRecoilValue } from 'recoil'
|
||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import { canvasState } from '@/store/canvasAtom'
|
|
||||||
import WithDraggable from '@/components/common/draggable/WithDraggable'
|
import WithDraggable from '@/components/common/draggable/WithDraggable'
|
||||||
import { usePopup } from '@/hooks/usePopup'
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
import { contextPopupPositionState } from '@/store/popupAtom'
|
import { contextPopupPositionState } from '@/store/popupAtom'
|
||||||
import { useState } from 'react'
|
import { useRef, useState, useEffect } from 'react'
|
||||||
|
import { useObjectBatch } from '@/hooks/object/useObjectBatch'
|
||||||
|
import { useEvent } from '@/hooks/useEvent'
|
||||||
|
|
||||||
export default function SizeSetting(props) {
|
export default function SizeSetting(props) {
|
||||||
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
||||||
const [settingTarget, setSettingTarget] = useState(1)
|
const [settingTarget, setSettingTarget] = useState(1)
|
||||||
const { id, pos = contextPopupPosition } = props
|
const { id, pos = contextPopupPosition, target } = props
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
const canvas = useRecoilValue(canvasState)
|
|
||||||
const { closePopup } = usePopup()
|
const { closePopup } = usePopup()
|
||||||
|
const { reSizeObjectBatch } = useObjectBatch({})
|
||||||
|
|
||||||
|
const widthRef = useRef(null)
|
||||||
|
const heightRef = useRef(null)
|
||||||
|
|
||||||
|
const { initEvent } = useEvent()
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
initEvent()
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const handleReSizeObject = () => {
|
||||||
|
const width = widthRef.current.value
|
||||||
|
const height = heightRef.current.value
|
||||||
|
|
||||||
|
reSizeObjectBatch(settingTarget, target, width, height)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<WithDraggable isShow={true} pos={pos}>
|
<WithDraggable isShow={true} pos={pos}>
|
||||||
<div className={`modal-pop-wrap ssm`}>
|
<div className={`modal-pop-wrap ssm mount`}>
|
||||||
<div className="modal-head">
|
<div className="modal-head">
|
||||||
<h1 className="title">サイズ変更 </h1>
|
<h1 className="title">{getMessage('modal.size.setting')} </h1>
|
||||||
<button className="modal-close" onClick={() => closePopup(id)}>
|
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||||
닫기
|
닫기
|
||||||
</button>
|
</button>
|
||||||
@ -30,11 +47,11 @@ export default function SizeSetting(props) {
|
|||||||
<div className="size-option-top">
|
<div className="size-option-top">
|
||||||
<div className="size-option-wrap">
|
<div className="size-option-wrap">
|
||||||
<div className="size-option mb5">
|
<div className="size-option mb5">
|
||||||
<input type="text" className="input-origin mr5" defaultValue={1000} readOnly />
|
<input type="text" className="input-origin mr5" value={target?.width.toFixed(0) * 10} readOnly={true} />
|
||||||
<span className="normal-font">mm</span>
|
<span className="normal-font">mm</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="size-option">
|
<div className="size-option">
|
||||||
<input type="text" className="input-origin mr5" defaultValue={1000} />
|
<input type="text" className="input-origin mr5" defaultValue={target?.width.toFixed(0) * 10} ref={widthRef} />
|
||||||
<span className="normal-font">mm</span>
|
<span className="normal-font">mm</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -43,11 +60,11 @@ export default function SizeSetting(props) {
|
|||||||
<div className="size-option-side">
|
<div className="size-option-side">
|
||||||
<div className="size-option-wrap">
|
<div className="size-option-wrap">
|
||||||
<div className="size-option mb5">
|
<div className="size-option mb5">
|
||||||
<input type="text" className="input-origin mr5" defaultValue={1000} readOnly />
|
<input type="text" className="input-origin mr5" value={target?.height.toFixed(0) * 10} readOnly={true} />
|
||||||
<span className="normal-font">mm</span>
|
<span className="normal-font">mm</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="size-option">
|
<div className="size-option">
|
||||||
<input type="text" className="input-origin mr5" defaultValue={1000} />
|
<input type="text" className="input-origin mr5" defaultValue={target?.height.toFixed(0) * 10} ref={heightRef} />
|
||||||
<span className="normal-font">mm</span>
|
<span className="normal-font">mm</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -62,7 +79,9 @@ export default function SizeSetting(props) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid-btn-wrap">
|
<div className="grid-btn-wrap">
|
||||||
<button className="btn-frame modal act">作成</button>
|
<button className="btn-frame modal act" onClick={() => handleReSizeObject()}>
|
||||||
|
{getMessage('write')}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -38,7 +38,7 @@ const PentagonDormer = forwardRef((props, refs) => {
|
|||||||
<div className="eaves-keraba-td">
|
<div className="eaves-keraba-td">
|
||||||
<div className="outline-form">
|
<div className="outline-form">
|
||||||
<div className="input-grid mr5" style={{ width: '60px' }}>
|
<div className="input-grid mr5" style={{ width: '60px' }}>
|
||||||
<input type="text" className="input-origin block" placeholder={0} ref={refs.offsetRef} />
|
<input type="text" className="input-origin block" placeholder={0} ref={refs.offsetRef} defaultValue={400} />
|
||||||
</div>
|
</div>
|
||||||
<span className="thin">mm</span>
|
<span className="thin">mm</span>
|
||||||
</div>
|
</div>
|
||||||
@ -60,7 +60,7 @@ const PentagonDormer = forwardRef((props, refs) => {
|
|||||||
<div className="eaves-keraba-td">
|
<div className="eaves-keraba-td">
|
||||||
<div className="outline-form">
|
<div className="outline-form">
|
||||||
<div className="input-grid mr5" style={{ width: '60px' }}>
|
<div className="input-grid mr5" style={{ width: '60px' }}>
|
||||||
<input type="text" className="input-origin block" placeholder={0} ref={refs.offsetWidthRef} />
|
<input type="text" className="input-origin block" placeholder={0} ref={refs.offsetWidthRef} defaultValue={300} />
|
||||||
</div>
|
</div>
|
||||||
<span className="thin">mm</span>
|
<span className="thin">mm</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -38,7 +38,7 @@ const TriangleDormer = forwardRef((props, refs) => {
|
|||||||
<div className="eaves-keraba-td">
|
<div className="eaves-keraba-td">
|
||||||
<div className="outline-form">
|
<div className="outline-form">
|
||||||
<div className="input-grid mr5" style={{ width: '60px' }}>
|
<div className="input-grid mr5" style={{ width: '60px' }}>
|
||||||
<input type="text" className="input-origin block" placeholder={0} ref={refs.offsetRef} />
|
<input type="text" className="input-origin block" placeholder={0} ref={refs.offsetRef} defaultValue={400} />
|
||||||
</div>
|
</div>
|
||||||
<span className="thin">mm</span>
|
<span className="thin">mm</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -0,0 +1,39 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import { useState } from 'react'
|
||||||
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
|
import WithDraggable from '@/components/common/draggable/withDraggable'
|
||||||
|
|
||||||
|
export default function PanelBatchStatistics() {
|
||||||
|
const { getMessage } = useMessage()
|
||||||
|
const [isFold, setIsFold] = useState(false)
|
||||||
|
const [pos, setPos] = useState({
|
||||||
|
x: 0,
|
||||||
|
y: 30,
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<WithDraggable isShow={true} handle=".penal-wrap" pos={pos}>
|
||||||
|
<div className={`penal-wrap ${!isFold ? 'act' : ''}`}>
|
||||||
|
<h2>{getMessage('modal.panel.batch.statistic')}</h2>
|
||||||
|
<button className="penal-arr" onClick={() => setIsFold(!isFold)}></button>
|
||||||
|
<div className="penal-table-wrap">
|
||||||
|
<table className="penal-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>{getMessage('modal.panel.batch.statistic.roof.shape')}</th>
|
||||||
|
<th>{getMessage('modal.panel.batch.statistic.power.generation.amount')} (kW)</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>{getMessage('modal.panel.batch.statistic.total')}</td>
|
||||||
|
<td className="al-r">0.000</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</WithDraggable>
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -8,6 +8,7 @@ import { useMessage } from '@/hooks/useMessage'
|
|||||||
import { useAxios } from '@/hooks/useAxios'
|
import { useAxios } from '@/hooks/useAxios'
|
||||||
import { useSwal } from '@/hooks/useSwal'
|
import { useSwal } from '@/hooks/useSwal'
|
||||||
import { usePopup } from '@/hooks/usePopup'
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
|
import { basicSettingState } from '@/store/settingAtom'
|
||||||
|
|
||||||
export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, setShowPlaceShapeModal }) {
|
export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, setShowPlaceShapeModal }) {
|
||||||
const [objectNo, setObjectNo] = useState('test123241008001') // 후에 삭제 필요
|
const [objectNo, setObjectNo] = useState('test123241008001') // 후에 삭제 필요
|
||||||
@ -16,22 +17,8 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set
|
|||||||
const [selectedRoofMaterial, setSelectedRoofMaterial] = useState(1)
|
const [selectedRoofMaterial, setSelectedRoofMaterial] = useState(1)
|
||||||
const [canvasSetting, setCanvasSetting] = useRecoilState(canvasSettingState)
|
const [canvasSetting, setCanvasSetting] = useRecoilState(canvasSettingState)
|
||||||
const { closePopup } = usePopup()
|
const { closePopup } = usePopup()
|
||||||
const [basicSetting, setBasicSettings] = useState({
|
const [basicSetting, setBasicSettings] = useRecoilState(basicSettingState)
|
||||||
roofSizeSet: 1,
|
const [image, setImage] = useState(null)
|
||||||
roofAngleSet: 'slope',
|
|
||||||
roofs: [
|
|
||||||
{
|
|
||||||
roofApply: true,
|
|
||||||
roofSeq: 1,
|
|
||||||
roofType: 1,
|
|
||||||
roofWidth: 200,
|
|
||||||
roofHeight: 200,
|
|
||||||
roofHajebichi: 200,
|
|
||||||
roofGap: 0,
|
|
||||||
roofLayout: 'parallel',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
})
|
|
||||||
|
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
const { get, post } = useAxios()
|
const { get, post } = useAxios()
|
||||||
@ -493,6 +480,24 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set
|
|||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>{getMessage('common.input.file')}</th>
|
||||||
|
<td>
|
||||||
|
<div className="flex-box">
|
||||||
|
<div className="img-edit-wrap">
|
||||||
|
<label className="img-edit-btn" htmlFor="img_file">
|
||||||
|
<span className="img-edit"></span>
|
||||||
|
{getMessage('common.input.file.load')}
|
||||||
|
</label>
|
||||||
|
<input type="file" id="img_file" style={{ display: 'none' }} onChange={(e) => setImage(e.target.files[0])} />
|
||||||
|
</div>
|
||||||
|
<div className="img-name-wrap">
|
||||||
|
<input type="text" className="input-origin al-l" defaultValue={''} value={image ? image.name : ''} readOnly />
|
||||||
|
{image && <button className="img-check" onClick={() => setImage(null)}></button>}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -49,7 +49,8 @@ const PlacementSurface = forwardRef((props, refs) => {
|
|||||||
{lines?.map((line, index) => (
|
{lines?.map((line, index) => (
|
||||||
<div className="eaves-keraba-item" id={index} key={index}>
|
<div className="eaves-keraba-item" id={index} key={index}>
|
||||||
<div className="eaves-keraba-th">
|
<div className="eaves-keraba-th">
|
||||||
{line.isDiagonal ? getMessage('modal.placement.surface.setting.diagonal.length') : num[index]}
|
{/*{line.isDiagonal ? getMessage('modal.placement.surface.setting.diagonal.length') : num[index]}*/}
|
||||||
|
{num[index]}
|
||||||
</div>
|
</div>
|
||||||
<div className="eaves-keraba-td">
|
<div className="eaves-keraba-td">
|
||||||
<div className="outline-form">
|
<div className="outline-form">
|
||||||
|
|||||||
@ -241,7 +241,7 @@ export default function PlacementSurfaceSetting({ id, pos = { x: 50, y: 230 } })
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<WithDraggable isShow={true} pos={{ x: 50, y: 230 }}>
|
<WithDraggable isShow={true} pos={{ x: 50, y: 230 }}>
|
||||||
<div className={`modal-pop-wrap l-2`}>
|
<div className={`modal-pop-wrap lr-2`}>
|
||||||
<div className="modal-head">
|
<div className="modal-head">
|
||||||
<h1 className="title">{getMessage('plan.menu.placement.surface.arrangement')} </h1>
|
<h1 className="title">{getMessage('plan.menu.placement.surface.arrangement')} </h1>
|
||||||
<button className="modal-close" onClick={() => closePopup(id)}>
|
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||||
@ -249,9 +249,15 @@ export default function PlacementSurfaceSetting({ id, pos = { x: 50, y: 230 } })
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="modal-body">
|
<div className="modal-body">
|
||||||
|
<div className="plane-frame-wrap">
|
||||||
|
<div className="plane-shape-wrap">
|
||||||
<div className="plane-shape-menu">
|
<div className="plane-shape-menu">
|
||||||
{types.map((type) => (
|
{types.map((type) => (
|
||||||
<button key={type.id} className={`shape-menu-box ${selectedType?.id === type.id ? 'act' : ''}`} onClick={() => setSelectedType(type)}>
|
<button
|
||||||
|
key={type.id}
|
||||||
|
className={`shape-menu-box ${selectedType?.id === type.id ? 'act' : ''}`}
|
||||||
|
onClick={() => setSelectedType(type)}
|
||||||
|
>
|
||||||
<div className="shape-box">
|
<div className="shape-box">
|
||||||
<Image
|
<Image
|
||||||
src={`/static/images/canvas/plane_shape0${type?.id}.svg`}
|
src={`/static/images/canvas/plane_shape0${type?.id}.svg`}
|
||||||
@ -273,14 +279,18 @@ export default function PlacementSurfaceSetting({ id, pos = { x: 50, y: 230 } })
|
|||||||
<button className="library-btn ico02" onClick={() => setYInversion(!yInversion)}></button>
|
<button className="library-btn ico02" onClick={() => setYInversion(!yInversion)}></button>
|
||||||
<button className="library-btn ico03" onClick={() => setXInversion(!xInversion)}></button>
|
<button className="library-btn ico03" onClick={() => setXInversion(!xInversion)}></button>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="plane-detail-wrap">
|
||||||
<PlacementSurface {...placementSurfaceProps} ref={surfaceRefs} />
|
<PlacementSurface {...placementSurfaceProps} ref={surfaceRefs} />
|
||||||
<div className="grid-btn-wrap">
|
<div className="plane-shape-btn">
|
||||||
<button className="btn-frame modal act" onClick={applySurfaces}>
|
<button className="btn-frame modal act" onClick={applySurfaces}>
|
||||||
{getMessage('write')}
|
{getMessage('write')}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</WithDraggable>
|
</WithDraggable>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,7 +16,7 @@ export default function RoofAllocationSetting(props) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<WithDraggable isShow={true} pos={pos}>
|
<WithDraggable isShow={true} pos={pos}>
|
||||||
<div className={`modal-pop-wrap ml`}>
|
<div className={`modal-pop-wrap ml mount`}>
|
||||||
<div className="modal-head">
|
<div className="modal-head">
|
||||||
<h1 className="title">{getMessage('plan.menu.estimate.roof.alloc')}</h1>
|
<h1 className="title">{getMessage('plan.menu.estimate.roof.alloc')}</h1>
|
||||||
<button className="modal-close" onClick={() => closePopup(id)}>
|
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||||
|
|||||||
@ -7,18 +7,21 @@ import { useRoofShapePassivitySetting } from '@/hooks/roofcover/useRoofShapePass
|
|||||||
import { usePopup } from '@/hooks/usePopup'
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
|
|
||||||
export default function RoofShapePassivitySetting({ id, pos = { x: 50, y: 230 } }) {
|
export default function RoofShapePassivitySetting({ id, pos = { x: 50, y: 230 } }) {
|
||||||
const { handleSave, handleConfirm, handleRollback, buttons, type, setType, TYPES, offsetRef, pitchRef } = useRoofShapePassivitySetting(id)
|
const { handleSave, handleConfirm, handleRollback, buttons, type, setType, TYPES, offsetRef, pitchRef, pitchText } =
|
||||||
|
useRoofShapePassivitySetting(id)
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
const { closePopup } = usePopup()
|
const { closePopup } = usePopup()
|
||||||
|
|
||||||
const eavesProps = {
|
const eavesProps = {
|
||||||
offsetRef,
|
offsetRef,
|
||||||
pitchRef,
|
pitchRef,
|
||||||
|
pitchText,
|
||||||
}
|
}
|
||||||
|
|
||||||
const gableProps = {
|
const gableProps = {
|
||||||
offsetRef,
|
offsetRef,
|
||||||
pitchRef,
|
pitchRef,
|
||||||
|
pitchText,
|
||||||
}
|
}
|
||||||
|
|
||||||
const shedProps = {
|
const shedProps = {
|
||||||
|
|||||||
@ -38,11 +38,14 @@ export default function RoofShapeSetting({ id, pos = { x: 50, y: 230 } }) {
|
|||||||
buttonMenu,
|
buttonMenu,
|
||||||
handleConfirm,
|
handleConfirm,
|
||||||
handleRollBack,
|
handleRollBack,
|
||||||
|
pitchText,
|
||||||
|
shedPitch,
|
||||||
|
setShedPitch,
|
||||||
} = useRoofShapeSetting(id)
|
} = useRoofShapeSetting(id)
|
||||||
const { closePopup } = usePopup()
|
const { closePopup } = usePopup()
|
||||||
|
|
||||||
const ridgeProps = { pitch, setPitch, eavesOffset, setEavesOffset }
|
const ridgeProps = { pitch, setPitch, eavesOffset, setEavesOffset, pitchText }
|
||||||
const patternProps = { pitch, setPitch, eavesOffset, setEavesOffset, gableOffset, setGableOffset }
|
const patternProps = { pitch, setPitch, eavesOffset, setEavesOffset, gableOffset, setGableOffset, pitchText }
|
||||||
const sideProps = {
|
const sideProps = {
|
||||||
pitch,
|
pitch,
|
||||||
setPitch,
|
setPitch,
|
||||||
@ -60,6 +63,8 @@ export default function RoofShapeSetting({ id, pos = { x: 50, y: 230 } }) {
|
|||||||
setHipAndGableWidth,
|
setHipAndGableWidth,
|
||||||
shedWidth,
|
shedWidth,
|
||||||
setShedWidth,
|
setShedWidth,
|
||||||
|
shedPitch,
|
||||||
|
setShedPitch,
|
||||||
hasSleeve,
|
hasSleeve,
|
||||||
setHasSleeve,
|
setHasSleeve,
|
||||||
buttonAct,
|
buttonAct,
|
||||||
@ -67,6 +72,7 @@ export default function RoofShapeSetting({ id, pos = { x: 50, y: 230 } }) {
|
|||||||
buttonMenu,
|
buttonMenu,
|
||||||
handleConfirm,
|
handleConfirm,
|
||||||
handleRollBack,
|
handleRollBack,
|
||||||
|
pitchText,
|
||||||
}
|
}
|
||||||
|
|
||||||
const directionProps = {
|
const directionProps = {
|
||||||
@ -78,6 +84,7 @@ export default function RoofShapeSetting({ id, pos = { x: 50, y: 230 } }) {
|
|||||||
setGableOffset,
|
setGableOffset,
|
||||||
shedWidth,
|
shedWidth,
|
||||||
setShedWidth,
|
setShedWidth,
|
||||||
|
pitchText,
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -1,7 +1,10 @@
|
|||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
|
import { useRecoilValue } from 'recoil'
|
||||||
|
import { ANGLE_TYPE, currentAngleTypeSelector } from '@/store/canvasAtom'
|
||||||
|
|
||||||
export default function Eaves({ offsetRef, pitchRef }) {
|
export default function Eaves({ offsetRef, pitchRef, pitchText }) {
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
|
const currentAngleType = useRecoilValue(currentAngleTypeSelector)
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="outline-form mb10">
|
<div className="outline-form mb10">
|
||||||
@ -9,9 +12,9 @@ export default function Eaves({ offsetRef, pitchRef }) {
|
|||||||
{getMessage('slope')}
|
{getMessage('slope')}
|
||||||
</span>
|
</span>
|
||||||
<div className="input-grid mr5">
|
<div className="input-grid mr5">
|
||||||
<input type="text" className="input-origin block" defaultValue={4} ref={pitchRef} />
|
<input type="text" className="input-origin block" defaultValue={currentAngleType === ANGLE_TYPE.SLOPE ? 4 : 21.8} ref={pitchRef} />
|
||||||
</div>
|
</div>
|
||||||
<span className="thin">寸</span>
|
<span className="thin">{pitchText}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="outline-form mb10">
|
<div className="outline-form mb10">
|
||||||
<span className="mr10" style={{ width: '63px' }}>
|
<span className="mr10" style={{ width: '63px' }}>
|
||||||
|
|||||||
@ -1,7 +1,10 @@
|
|||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
|
import { useRecoilValue } from 'recoil'
|
||||||
|
import { ANGLE_TYPE, currentAngleTypeSelector } from '@/store/canvasAtom'
|
||||||
|
|
||||||
export default function Gable({ offsetRef, pitchRef }) {
|
export default function Gable({ offsetRef, pitchRef, pitchText }) {
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
|
const currentAngleType = useRecoilValue(currentAngleTypeSelector)
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="outline-form mb10">
|
<div className="outline-form mb10">
|
||||||
@ -9,9 +12,9 @@ export default function Gable({ offsetRef, pitchRef }) {
|
|||||||
{getMessage('slope')}
|
{getMessage('slope')}
|
||||||
</span>
|
</span>
|
||||||
<div className="input-grid mr5">
|
<div className="input-grid mr5">
|
||||||
<input type="text" className="input-origin block" defaultValue={4} ref={pitchRef} />
|
<input type="text" className="input-origin block" defaultValue={currentAngleType === ANGLE_TYPE.SLOPE ? 4 : 21.8} ref={pitchRef} />
|
||||||
</div>
|
</div>
|
||||||
<span className="thin">寸</span>
|
<span className="thin">{pitchText}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="outline-form mb10">
|
<div className="outline-form mb10">
|
||||||
<span className="mr10" style={{ width: '63px' }}>
|
<span className="mr10" style={{ width: '63px' }}>
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import { onlyNumberInputChange, onlyNumberWithDotInputChange } from '@/util/input-utils'
|
import { onlyNumberInputChange, onlyNumberWithDotInputChange } from '@/util/input-utils'
|
||||||
|
|
||||||
export default function Direction({ pitch, setPitch, eavesOffset, setEavesOffset, gableOffset, setGableOffset, shedWidth, setShedWidth }) {
|
export default function Direction({ pitch, setPitch, eavesOffset, setEavesOffset, gableOffset, setGableOffset, shedWidth, setShedWidth, pitchText }) {
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
return (
|
return (
|
||||||
<div className="setting-box">
|
<div className="setting-box">
|
||||||
@ -12,7 +12,7 @@ export default function Direction({ pitch, setPitch, eavesOffset, setEavesOffset
|
|||||||
<div className="input-grid mr5" style={{ width: '100px' }}>
|
<div className="input-grid mr5" style={{ width: '100px' }}>
|
||||||
<input type="text" className="input-origin block" value={pitch} onChange={(e) => onlyNumberWithDotInputChange(e, setPitch)} />
|
<input type="text" className="input-origin block" value={pitch} onChange={(e) => onlyNumberWithDotInputChange(e, setPitch)} />
|
||||||
</div>
|
</div>
|
||||||
<span className="thin">{getMessage('size')}</span>
|
<span className="thin">{pitchText}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="outline-form mb10">
|
<div className="outline-form mb10">
|
||||||
<span className="mr10" style={{ width: '60px' }}>
|
<span className="mr10" style={{ width: '60px' }}>
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import { onlyNumberInputChange, onlyNumberWithDotInputChange } from '@/util/inpu
|
|||||||
|
|
||||||
export default function Pattern(props) {
|
export default function Pattern(props) {
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
const { pitch, setPitch, eavesOffset, setEavesOffset, gableOffset, setGableOffset } = props
|
const { pitch, setPitch, eavesOffset, setEavesOffset, gableOffset, setGableOffset, pitchText } = props
|
||||||
return (
|
return (
|
||||||
<div className="setting-box">
|
<div className="setting-box">
|
||||||
<div className="outline-form mb10">
|
<div className="outline-form mb10">
|
||||||
@ -13,7 +13,7 @@ export default function Pattern(props) {
|
|||||||
<div className="input-grid mr5" style={{ width: '100px' }}>
|
<div className="input-grid mr5" style={{ width: '100px' }}>
|
||||||
<input type="text" className="input-origin block" value={pitch} onChange={(e) => onlyNumberWithDotInputChange(e, setPitch)} />
|
<input type="text" className="input-origin block" value={pitch} onChange={(e) => onlyNumberWithDotInputChange(e, setPitch)} />
|
||||||
</div>
|
</div>
|
||||||
<span className="thin"> {getMessage('size')}</span>
|
<span className="thin"> {pitchText}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="outline-form mb10">
|
<div className="outline-form mb10">
|
||||||
<span className="mr10" style={{ width: '60px' }}>
|
<span className="mr10" style={{ width: '60px' }}>
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import { onlyNumberInputChange, onlyNumberWithDotInputChange } from '@/util/inpu
|
|||||||
|
|
||||||
export default function Ridge(props) {
|
export default function Ridge(props) {
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
const { pitch, setPitch, eavesOffset, setEavesOffset } = props
|
const { pitch, setPitch, eavesOffset, setEavesOffset, pitchText } = props
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="setting-box">
|
<div className="setting-box">
|
||||||
@ -15,7 +15,7 @@ export default function Ridge(props) {
|
|||||||
<div className="input-grid mr5" style={{ width: '100px' }}>
|
<div className="input-grid mr5" style={{ width: '100px' }}>
|
||||||
<input type="text" className="input-origin block" value={pitch} onChange={(e) => onlyNumberWithDotInputChange(e, setPitch)} />
|
<input type="text" className="input-origin block" value={pitch} onChange={(e) => onlyNumberWithDotInputChange(e, setPitch)} />
|
||||||
</div>
|
</div>
|
||||||
<span className="thin">{getMessage('size')}</span>
|
<span className="thin">{pitchText}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="outline-form">
|
<div className="outline-form">
|
||||||
<span className="mr10" style={{ width: '24px' }}>
|
<span className="mr10" style={{ width: '24px' }}>
|
||||||
|
|||||||
@ -32,14 +32,17 @@ export default function Side(props) {
|
|||||||
buttonMenu,
|
buttonMenu,
|
||||||
handleConfirm,
|
handleConfirm,
|
||||||
handleRollBack,
|
handleRollBack,
|
||||||
|
pitchText,
|
||||||
|
shedPitch,
|
||||||
|
setShedPitch,
|
||||||
} = props
|
} = props
|
||||||
|
|
||||||
const eavesProps = { pitch, setPitch, eavesOffset, setEavesOffset }
|
const eavesProps = { pitch, setPitch, eavesOffset, setEavesOffset, pitchText }
|
||||||
const gableProps = { gableOffset, setGableOffset }
|
const gableProps = { gableOffset, setGableOffset }
|
||||||
const wallProps = { sleeveOffset, setSleeveOffset, hasSleeve, setHasSleeve }
|
const wallProps = { sleeveOffset, setSleeveOffset, hasSleeve, setHasSleeve }
|
||||||
const hipAndGableProps = { pitch, setPitch, eavesOffset, setEavesOffset, hipAndGableWidth, setHipAndGableWidth }
|
const hipAndGableProps = { pitch, setPitch, eavesOffset, setEavesOffset, hipAndGableWidth, setHipAndGableWidth, pitchText }
|
||||||
const jerkinheadProps = { gableOffset, setGableOffset, jerkinHeadWidth, setJerkinHeadWidth, jerkinHeadPitch, setJerkinHeadPitch }
|
const jerkinheadProps = { gableOffset, setGableOffset, jerkinHeadWidth, setJerkinHeadWidth, jerkinHeadPitch, setJerkinHeadPitch, pitchText }
|
||||||
const shedProps = { shedWidth, setShedWidth }
|
const shedProps = { shedWidth, setShedWidth, shedPitch, setShedPitch, pitchText }
|
||||||
|
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import { onlyNumberInputChange, onlyNumberWithDotInputChange } from '@/util/input-utils'
|
import { onlyNumberInputChange, onlyNumberWithDotInputChange } from '@/util/input-utils'
|
||||||
|
|
||||||
export default function Eaves({ pitch, setPitch, eavesOffset, setEavesOffset }) {
|
export default function Eaves({ pitch, setPitch, eavesOffset, setEavesOffset, pitchText }) {
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -12,7 +12,7 @@ export default function Eaves({ pitch, setPitch, eavesOffset, setEavesOffset })
|
|||||||
<div className="input-grid mr5" style={{ width: '100px' }}>
|
<div className="input-grid mr5" style={{ width: '100px' }}>
|
||||||
<input type="text" className="input-origin block" value={pitch} onChange={(e) => onlyNumberWithDotInputChange(e, setPitch)} />
|
<input type="text" className="input-origin block" value={pitch} onChange={(e) => onlyNumberWithDotInputChange(e, setPitch)} />
|
||||||
</div>
|
</div>
|
||||||
<span className="thin">{getMessage('size')}</span>
|
<span className="thin">{pitchText}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="outline-form">
|
<div className="outline-form">
|
||||||
<span className="mr10" style={{ width: '24px' }}>
|
<span className="mr10" style={{ width: '24px' }}>
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import { onlyNumberInputChange, onlyNumberWithDotInputChange } from '@/util/input-utils'
|
import { onlyNumberInputChange, onlyNumberWithDotInputChange } from '@/util/input-utils'
|
||||||
|
|
||||||
export default function HipAndGable({ pitch, setPitch, eavesOffset, setEavesOffset, hipAndGableWidth, setHipAndGableWidth }) {
|
export default function HipAndGable({ pitch, setPitch, eavesOffset, setEavesOffset, hipAndGableWidth, setHipAndGableWidth, pitchText }) {
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -12,7 +12,7 @@ export default function HipAndGable({ pitch, setPitch, eavesOffset, setEavesOffs
|
|||||||
<div className="input-grid mr5" style={{ width: '100px' }}>
|
<div className="input-grid mr5" style={{ width: '100px' }}>
|
||||||
<input type="text" className="input-origin block" value={pitch} onChange={(e) => onlyNumberWithDotInputChange(e, setPitch)} />
|
<input type="text" className="input-origin block" value={pitch} onChange={(e) => onlyNumberWithDotInputChange(e, setPitch)} />
|
||||||
</div>
|
</div>
|
||||||
<span className="thin">{getMessage('size')}</span>
|
<span className="thin">{pitchText}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="outline-form mb10">
|
<div className="outline-form mb10">
|
||||||
<span className="mr10" style={{ width: '60px' }}>
|
<span className="mr10" style={{ width: '60px' }}>
|
||||||
|
|||||||
@ -1,7 +1,15 @@
|
|||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import { onlyNumberInputChange, onlyNumberWithDotInputChange } from '@/util/input-utils'
|
import { onlyNumberInputChange, onlyNumberWithDotInputChange } from '@/util/input-utils'
|
||||||
|
|
||||||
export default function Jerkinhead({ gableOffset, setGableOffset, jerkinHeadWidth, setJerkinHeadWidth, jerkinHeadPitch, setJerkinHeadPitch }) {
|
export default function Jerkinhead({
|
||||||
|
gableOffset,
|
||||||
|
setGableOffset,
|
||||||
|
jerkinHeadWidth,
|
||||||
|
setJerkinHeadWidth,
|
||||||
|
jerkinHeadPitch,
|
||||||
|
setJerkinHeadPitch,
|
||||||
|
pitchText,
|
||||||
|
}) {
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -35,7 +43,7 @@ export default function Jerkinhead({ gableOffset, setGableOffset, jerkinHeadWidt
|
|||||||
onChange={(e) => onlyNumberWithDotInputChange(e, setJerkinHeadPitch)}
|
onChange={(e) => onlyNumberWithDotInputChange(e, setJerkinHeadPitch)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<span className="thin">{getMessage('size')}</span>
|
<span className="thin">{pitchText}</span>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -1,10 +1,17 @@
|
|||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import { onlyNumberInputChange } from '@/util/input-utils'
|
import { onlyNumberInputChange, onlyNumberWithDotInputChange } from '@/util/input-utils'
|
||||||
|
|
||||||
export default function Shed({ shedWidth, setShedWidth }) {
|
export default function Shed({ shedWidth, setShedWidth, shedPitch, setShedPitch, pitchText }) {
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
<div className="outline-form mb10">
|
||||||
|
<span className="mr10">{getMessage('slope')}</span>
|
||||||
|
<div className="input-grid mr5" style={{ width: '100px' }}>
|
||||||
|
<input type="text" className="input-origin block" value={shedPitch} onChange={(e) => onlyNumberWithDotInputChange(e, setShedPitch)} />
|
||||||
|
</div>
|
||||||
|
<span className="thin">{pitchText}</span>
|
||||||
|
</div>
|
||||||
<div className="outline-form">
|
<div className="outline-form">
|
||||||
<span className="mr10">{getMessage('shed.width')}</span>
|
<span className="mr10">{getMessage('shed.width')}</span>
|
||||||
<div className="input-grid mr5" style={{ width: '100px' }}>
|
<div className="input-grid mr5" style={{ width: '100px' }}>
|
||||||
|
|||||||
@ -1,211 +1,20 @@
|
|||||||
import { useRecoilState, useRecoilValue } from 'recoil'
|
|
||||||
import { settingModalSecondOptionsState } from '@/store/settingAtom'
|
|
||||||
import { useMessage } from '@/hooks/useMessage'
|
|
||||||
import React, { useEffect, useState } from 'react'
|
import React, { useEffect, useState } from 'react'
|
||||||
import { useAxios } from '@/hooks/useAxios'
|
import { useCanvasSetting } from '@/hooks/option/useCanvasSetting'
|
||||||
import { useSwal } from '@/hooks/useSwal'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import { useFirstOption } from '@/hooks/option/useFirstOption'
|
|
||||||
import { setSurfaceShapePattern } from '@/util/canvas-util'
|
|
||||||
import { canvasState } from '@/store/canvasAtom'
|
|
||||||
import { POLYGON_TYPE } from '@/common/common'
|
|
||||||
|
|
||||||
export default function FirstOption() {
|
export default function FirstOption() {
|
||||||
const [objectNo, setObjectNo] = useState('test123240912001') // 이후 삭제 필요
|
const [objectNo, setObjectNo] = useState('test123240912001') // 이후 삭제 필요
|
||||||
const { settingModalFirstOptions, setSettingModalFirstOptions } = useFirstOption()
|
const { settingModalFirstOptions, setSettingModalFirstOptions } = useCanvasSetting()
|
||||||
const [settingModalSecondOptions, setSettingModalSecondOptions] = useRecoilState(settingModalSecondOptionsState)
|
const { settingModalSecondOptions, setSettingModalSecondOptions } = useCanvasSetting()
|
||||||
const { option1, option2, dimensionDisplay } = settingModalFirstOptions
|
|
||||||
const { option3, option4 } = settingModalSecondOptions
|
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
const { get, post } = useAxios()
|
|
||||||
const { swalFire } = useSwal()
|
const { fetchSettings, frontSettings, onClickOption } = useCanvasSetting()
|
||||||
const canvas = useRecoilValue(canvasState)
|
|
||||||
|
|
||||||
// 데이터를 최초 한 번만 조회
|
// 데이터를 최초 한 번만 조회
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log('FirstOption useEffect 실행')
|
console.log('FirstOption useEffect 실행')
|
||||||
fetchSettings()
|
|
||||||
}, [objectNo])
|
}, [objectNo])
|
||||||
|
|
||||||
// Canvas Setting 조회 및 초기화
|
|
||||||
const fetchSettings = async () => {
|
|
||||||
try {
|
|
||||||
const res = await get({ url: `/api/canvas-management/canvas-settings/by-object/${objectNo}` })
|
|
||||||
const optionData1 = settingModalFirstOptions.option1.map((item) => ({ ...item, selected: res[item.column] }))
|
|
||||||
const optionData2 = settingModalFirstOptions.option2.map((item) => ({ ...item, selected: res[item.column] }))
|
|
||||||
const optionData5 = settingModalFirstOptions.dimensionDisplay.map((item) => ({ ...item, selected: res[item.column] }))
|
|
||||||
const optionData3 = settingModalSecondOptions.option3.map((item) => ({ ...item }))
|
|
||||||
const optionData4 = settingModalSecondOptions.option4.map((item) => ({ ...item, selected: res[item.column] }))
|
|
||||||
|
|
||||||
// 데이터 설정
|
|
||||||
setSettingModalFirstOptions({
|
|
||||||
option1: optionData1,
|
|
||||||
option2: optionData2,
|
|
||||||
dimensionDisplay: optionData5,
|
|
||||||
})
|
|
||||||
|
|
||||||
setSettingModalSecondOptions({
|
|
||||||
option3: optionData3,
|
|
||||||
option4: optionData4,
|
|
||||||
})
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Data fetching error:', error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const onClickOption = async (option) => {
|
|
||||||
option.selected = !option.selected
|
|
||||||
|
|
||||||
setSettingModalFirstOptions({ option1, option2, dimensionDisplay })
|
|
||||||
setSettingModalSecondOptions({ option3, option4 })
|
|
||||||
|
|
||||||
try {
|
|
||||||
// 서버에 전송할 데이터
|
|
||||||
const dataToSend = {
|
|
||||||
firstOption1: option1.map((item) => ({
|
|
||||||
column: item.column,
|
|
||||||
selected: item.selected,
|
|
||||||
})),
|
|
||||||
firstOption2: option2.map((item) => ({
|
|
||||||
column: item.column,
|
|
||||||
selected: item.selected,
|
|
||||||
})),
|
|
||||||
firstOption3: dimensionDisplay.map((item) => ({
|
|
||||||
column: item.column,
|
|
||||||
selected: item.selected,
|
|
||||||
})),
|
|
||||||
// secondOption1: secondOptions[0].option1.map((item) => ({
|
|
||||||
// name: item.id,
|
|
||||||
// name: item.name,
|
|
||||||
// // 필요한 경우 데이터 항목 추가
|
|
||||||
// })),
|
|
||||||
secondOption2: option4.map((item) => ({
|
|
||||||
column: item.column,
|
|
||||||
selected: item.selected,
|
|
||||||
})),
|
|
||||||
}
|
|
||||||
|
|
||||||
const patternData = {
|
|
||||||
objectNo,
|
|
||||||
//디스플레이 설정(다중)
|
|
||||||
allocDisplay: dataToSend.firstOption1[0].selected,
|
|
||||||
outlineDisplay: dataToSend.firstOption1[1].selected,
|
|
||||||
gridDisplay: dataToSend.firstOption1[2].selected,
|
|
||||||
lineDisplay: dataToSend.firstOption1[3].selected,
|
|
||||||
wordDisplay: dataToSend.firstOption1[4].selected,
|
|
||||||
circuitNumDisplay: dataToSend.firstOption1[5].selected,
|
|
||||||
flowDisplay: dataToSend.firstOption1[6].selected,
|
|
||||||
trestleDisplay: dataToSend.firstOption1[7].selected,
|
|
||||||
totalDisplay: dataToSend.firstOption1[8].selected,
|
|
||||||
//차수 표시(다건)
|
|
||||||
corridorDimension: dataToSend.firstOption3[0].selected,
|
|
||||||
realDimension: dataToSend.firstOption3[1].selected,
|
|
||||||
noneDimension: dataToSend.firstOption3[2].selected,
|
|
||||||
//화면 표시(다중)
|
|
||||||
onlyBorder: dataToSend.firstOption2[0].selected,
|
|
||||||
lineHatch: dataToSend.firstOption2[1].selected,
|
|
||||||
allPainted: dataToSend.firstOption2[2].selected,
|
|
||||||
//흡착범위 설정(단건)
|
|
||||||
adsorpRangeSmall: dataToSend.secondOption2[0].selected,
|
|
||||||
adsorpRangeSmallSemi: dataToSend.secondOption2[1].selected,
|
|
||||||
adsorpRangeMedium: dataToSend.secondOption2[2].selected,
|
|
||||||
adsorpRangeLarge: dataToSend.secondOption2[3].selected,
|
|
||||||
}
|
|
||||||
|
|
||||||
// HTTP POST 요청 보내기
|
|
||||||
await post({ url: `/api/canvas-management/canvas-settings`, data: patternData }).then((res) => {
|
|
||||||
swalFire({ text: getMessage(res.returnMessage) })
|
|
||||||
})
|
|
||||||
} catch (error) {
|
|
||||||
swalFire({ text: getMessage(res.returnMessage), icon: 'error' })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const onClickOnlyOne = async (item) => {
|
|
||||||
//화면 표시
|
|
||||||
if (item.column === 'onlyBorder' || item.column === 'lineHatch' || item.column === 'allPainted') {
|
|
||||||
const options2 = settingModalFirstOptions?.option2.map((option2) => {
|
|
||||||
option2.selected = option2.id === item.id
|
|
||||||
return option2
|
|
||||||
})
|
|
||||||
|
|
||||||
const polygons = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF)
|
|
||||||
|
|
||||||
polygons.forEach((polygon) => {
|
|
||||||
setSurfaceShapePattern(polygon, item.column)
|
|
||||||
})
|
|
||||||
|
|
||||||
//치수 표시
|
|
||||||
} else {
|
|
||||||
const options = settingModalFirstOptions?.dimensionDisplay.map((option) => {
|
|
||||||
option.selected = option.id === item.id
|
|
||||||
return option
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
setSettingModalFirstOptions({ option1, option2, dimensionDisplay })
|
|
||||||
|
|
||||||
try {
|
|
||||||
// 서버에 전송할 데이터
|
|
||||||
const dataToSend = {
|
|
||||||
firstOption1: option1.map((item) => ({
|
|
||||||
column: item.column,
|
|
||||||
selected: item.selected,
|
|
||||||
})),
|
|
||||||
firstOption2: option2.map((item) => ({
|
|
||||||
column: item.column,
|
|
||||||
selected: item.selected,
|
|
||||||
})),
|
|
||||||
firstOption3: dimensionDisplay.map((item) => ({
|
|
||||||
column: item.column,
|
|
||||||
selected: item.selected,
|
|
||||||
})),
|
|
||||||
// secondOption1: secondOptions[0].option1.map((item) => ({
|
|
||||||
// name: item.id,
|
|
||||||
// name: item.name,
|
|
||||||
// // 필요한 경우 데이터 항목 추가
|
|
||||||
// })),
|
|
||||||
secondOption2: option4.map((item) => ({
|
|
||||||
column: item.column,
|
|
||||||
selected: item.selected,
|
|
||||||
})),
|
|
||||||
}
|
|
||||||
|
|
||||||
const patternData = {
|
|
||||||
objectNo,
|
|
||||||
//디스플레이 설정(다중)
|
|
||||||
allocDisplay: dataToSend.firstOption1[0].selected,
|
|
||||||
outlineDisplay: dataToSend.firstOption1[1].selected,
|
|
||||||
gridDisplay: dataToSend.firstOption1[2].selected,
|
|
||||||
lineDisplay: dataToSend.firstOption1[3].selected,
|
|
||||||
wordDisplay: dataToSend.firstOption1[4].selected,
|
|
||||||
circuitNumDisplay: dataToSend.firstOption1[5].selected,
|
|
||||||
flowDisplay: dataToSend.firstOption1[6].selected,
|
|
||||||
trestleDisplay: dataToSend.firstOption1[7].selected,
|
|
||||||
totalDisplay: dataToSend.firstOption1[8].selected,
|
|
||||||
//차수 표시(다건)
|
|
||||||
corridorDimension: dataToSend.firstOption3[0].selected,
|
|
||||||
realDimension: dataToSend.firstOption3[1].selected,
|
|
||||||
noneDimension: dataToSend.firstOption3[2].selected,
|
|
||||||
//화면 표시(다중)
|
|
||||||
onlyBorder: dataToSend.firstOption2[0].selected,
|
|
||||||
lineHatch: dataToSend.firstOption2[1].selected,
|
|
||||||
allPainted: dataToSend.firstOption2[2].selected,
|
|
||||||
//흡착범위 설정(단건)
|
|
||||||
adsorpRangeSmall: dataToSend.secondOption2[0].selected,
|
|
||||||
adsorpRangeSmallSemi: dataToSend.secondOption2[1].selected,
|
|
||||||
adsorpRangeMedium: dataToSend.secondOption2[2].selected,
|
|
||||||
adsorpRangeLarge: dataToSend.secondOption2[3].selected,
|
|
||||||
}
|
|
||||||
|
|
||||||
// HTTP POST 요청 보내기
|
|
||||||
await post({ url: `/api/canvas-management/canvas-settings`, data: patternData }).then((res) => {
|
|
||||||
swalFire({ text: getMessage(res.returnMessage) })
|
|
||||||
})
|
|
||||||
} catch (error) {
|
|
||||||
swalFire({ text: getMessage(res.returnMessage), icon: 'error' })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="modal-check-btn-wrap">
|
<div className="modal-check-btn-wrap">
|
||||||
@ -225,7 +34,7 @@ export default function FirstOption() {
|
|||||||
<div className="flex-check-box for-line">
|
<div className="flex-check-box for-line">
|
||||||
{settingModalFirstOptions &&
|
{settingModalFirstOptions &&
|
||||||
settingModalFirstOptions.dimensionDisplay.map((item) => (
|
settingModalFirstOptions.dimensionDisplay.map((item) => (
|
||||||
<button key={item.id} className={`check-btn ${item.selected ? 'act' : ''}`} onClick={(e) => onClickOnlyOne(item)}>
|
<button key={item.id} className={`check-btn ${item.selected ? 'act' : ''}`} onClick={(e) => onClickOption(item)}>
|
||||||
<span className="check-area"></span>
|
<span className="check-area"></span>
|
||||||
<span className="title-area">{getMessage(item.name)}</span>
|
<span className="title-area">{getMessage(item.name)}</span>
|
||||||
</button>
|
</button>
|
||||||
@ -237,7 +46,7 @@ export default function FirstOption() {
|
|||||||
<div className="flex-check-box for-line">
|
<div className="flex-check-box for-line">
|
||||||
{settingModalFirstOptions &&
|
{settingModalFirstOptions &&
|
||||||
settingModalFirstOptions.option2.map((item) => (
|
settingModalFirstOptions.option2.map((item) => (
|
||||||
<button key={item.id} className={`check-btn ${item.selected ? 'act' : ''}`} onClick={(e) => onClickOnlyOne(item)}>
|
<button key={item.id} className={`check-btn ${item.selected ? 'act' : ''}`} onClick={(e) => onClickOption(item)}>
|
||||||
<span className="check-area"></span>
|
<span className="check-area"></span>
|
||||||
<span className="title-area">{getMessage(item.name)}</span>
|
<span className="title-area">{getMessage(item.name)}</span>
|
||||||
</button>
|
</button>
|
||||||
|
|||||||