diff --git a/package-lock.json b/package-lock.json index 2de12e1..b96b497 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,12 +13,17 @@ "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", "antd": "^5.4.0", + "axios": "^1.4.0", + "hooks": "^0.3.2", "react": "^18.2.0", "react-bootstrap": "^2.7.2", + "react-daum-postcode": "^3.1.1", "react-dom": "^18.2.0", + "react-router": "^6.10.0", "react-router-dom": "^6.10.0", "react-scripts": "5.0.1", "reactstrap": "^9.1.8", + "three": "^0.152.2", "web-vitals": "^2.1.4" } }, @@ -4445,9 +4450,9 @@ "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" }, "node_modules/@types/react": { - "version": "18.0.28", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.28.tgz", - "integrity": "sha512-RD0ivG1kEztNBdoAK7lekI9M+azSnitIn85h4iOiaLjaTrMjzslhaqCGaI4IyCJ1RljWiLCEu4jyrLLgqxBTew==", + "version": "18.2.7", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.7.tgz", + "integrity": "sha512-ojrXpSH2XFCmHm7Jy3q44nXDyN54+EYKP2lBhJ2bqfyPj6cIUW/FZW/Csdia34NQgq7KYcAlHi5184m4X88+yw==", "dependencies": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -5440,6 +5445,29 @@ "node": ">=4" } }, + "node_modules/axios": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz", + "integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==", + "dependencies": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/axios/node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/axobject-query": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz", @@ -9104,6 +9132,14 @@ "he": "bin/he" } }, + "node_modules/hooks": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/hooks/-/hooks-0.3.2.tgz", + "integrity": "sha512-TqeFzUf12rSzcbm5lUls81jimUC8TmXZ4ANPxxeeMou09hrjBcHYhAQ0WgyN5YqNCXOzz7L6xVNl/+ctFuSeOw==", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/hoopy": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz", @@ -14476,6 +14512,11 @@ "node": ">= 0.10" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "node_modules/psl": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", @@ -15275,6 +15316,14 @@ } } }, + "node_modules/react-daum-postcode": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/react-daum-postcode/-/react-daum-postcode-3.1.1.tgz", + "integrity": "sha512-IFlC8XBSK+uobSIBHaWlxeecYpv9RhCFNu4YJ3+CrfGyEVdc4+yaaUH6BIfJbTZOybVx0V3s4nUeAEsssXBNJg==", + "peerDependencies": { + "react": ">=16.8.0" + } + }, "node_modules/react-dev-utils": { "version": "12.0.1", "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz", @@ -17046,6 +17095,11 @@ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" }, + "node_modules/three": { + "version": "0.152.2", + "resolved": "https://registry.npmjs.org/three/-/three-0.152.2.tgz", + "integrity": "sha512-Ff9zIpSfkkqcBcpdiFo2f35vA9ZucO+N8TNacJOqaEE6DrB0eufItVMib8bK8Pcju/ZNT6a7blE1GhTpkdsILw==" + }, "node_modules/throat": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.2.tgz", @@ -21514,9 +21568,9 @@ "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" }, "@types/react": { - "version": "18.0.28", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.28.tgz", - "integrity": "sha512-RD0ivG1kEztNBdoAK7lekI9M+azSnitIn85h4iOiaLjaTrMjzslhaqCGaI4IyCJ1RljWiLCEu4jyrLLgqxBTew==", + "version": "18.2.7", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.7.tgz", + "integrity": "sha512-ojrXpSH2XFCmHm7Jy3q44nXDyN54+EYKP2lBhJ2bqfyPj6cIUW/FZW/Csdia34NQgq7KYcAlHi5184m4X88+yw==", "requires": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -22267,6 +22321,28 @@ "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.6.3.tgz", "integrity": "sha512-/BQzOX780JhsxDnPpH4ZiyrJAzcd8AfzFPkv+89veFSr1rcMjuq2JDCwypKaPeB6ljHp9KjXhPpjgCvQlWYuqg==" }, + "axios": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz", + "integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==", + "requires": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + }, + "dependencies": { + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + } + } + }, "axobject-query": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz", @@ -24949,6 +25025,11 @@ "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" }, + "hooks": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/hooks/-/hooks-0.3.2.tgz", + "integrity": "sha512-TqeFzUf12rSzcbm5lUls81jimUC8TmXZ4ANPxxeeMou09hrjBcHYhAQ0WgyN5YqNCXOzz7L6xVNl/+ctFuSeOw==" + }, "hoopy": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz", @@ -28658,6 +28739,11 @@ } } }, + "proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "psl": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", @@ -29200,6 +29286,12 @@ "warning": "^4.0.3" } }, + "react-daum-postcode": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/react-daum-postcode/-/react-daum-postcode-3.1.1.tgz", + "integrity": "sha512-IFlC8XBSK+uobSIBHaWlxeecYpv9RhCFNu4YJ3+CrfGyEVdc4+yaaUH6BIfJbTZOybVx0V3s4nUeAEsssXBNJg==", + "requires": {} + }, "react-dev-utils": { "version": "12.0.1", "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz", @@ -30507,6 +30599,11 @@ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" }, + "three": { + "version": "0.152.2", + "resolved": "https://registry.npmjs.org/three/-/three-0.152.2.tgz", + "integrity": "sha512-Ff9zIpSfkkqcBcpdiFo2f35vA9ZucO+N8TNacJOqaEE6DrB0eufItVMib8bK8Pcju/ZNT6a7blE1GhTpkdsILw==" + }, "throat": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.2.tgz", diff --git a/package.json b/package.json index 14ee776..578ef1b 100644 --- a/package.json +++ b/package.json @@ -8,14 +8,17 @@ "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", "antd": "^5.4.0", - "axios": "^1.3.5", + "axios": "^1.4.0", + "hooks": "^0.3.2", "react": "^18.2.0", "react-bootstrap": "^2.7.2", + "react-daum-postcode": "^3.1.1", "react-dom": "^18.2.0", "react-router": "^6.10.0", "react-router-dom": "^6.10.0", "react-scripts": "5.0.1", "reactstrap": "^9.1.8", + "three": "^0.152.2", "web-vitals": "^2.1.4" }, "scripts": { diff --git a/src/App.js b/src/App.js index 2445085..4625d47 100644 --- a/src/App.js +++ b/src/App.js @@ -4,12 +4,18 @@ import './App.css'; import LoginPage from "./page/login/LoginPage" import RegisterPage from "./page/login/Register"; -import LoginPage2 from "./page/login/LoginPage2" - +import LoginPage2 from "./page/login/LoginPage2"; +import FindAddress from "./page/login/FindAddress"; import DataManage from "./page/manager/DataManage"; -import OrderManage from "./page/manager/OrderManage"; -import MainPageLayout from "./page/MainPageLayout" +import MainPageLayout from "./page/MainPageLayout"; +import Upload from "./page/manager/Upload"; +import LoadResultManage from "./page/manager/LoadResultManage"; +import SetPallet from "./page/manager/SetPallet"; +import MainPageLayoutForUser from "./page/MainPageLayoutForUser"; +import GoodsRegister from "./page/user/GoodsRegister"; +import OrderDelivery from "./page/user/OrderDelivery"; +import Mapping from "./page/manager/Mapping"; function App() { return ( @@ -17,13 +23,20 @@ function App() { }/> }/> - }/> }> }/> - }/> + }/> + + }> + }/> + }/> + }/> + }/> + }/> + }/> ); diff --git a/src/component/CheckDupId.module.css b/src/component/CheckDupId.module.css new file mode 100644 index 0000000..07352c7 --- /dev/null +++ b/src/component/CheckDupId.module.css @@ -0,0 +1,19 @@ +.h1 { + text-align: center; + margin-top: 100px; +} +.page_wrapper { + background-color: #abcdef; + border: 5px solid #abcdef; + border-radius:10px; + width: 600px; + height: 100px; + margin-top: 70px; + margin-left: 130px; +} +.check_form { + margin-top: 30px; + margin-left:110px; + width : 500px; + display:flex; +} \ No newline at end of file diff --git a/src/component/LoginPage.module.css b/src/component/LoginPage.module.css index 19de839..be55fd7 100644 --- a/src/component/LoginPage.module.css +++ b/src/component/LoginPage.module.css @@ -16,15 +16,9 @@ } span { font-size:18px; - margin-right:25px; + /*margin-right:25px;*/ } -span:hover { - color: black; -} - - - .page_middle { height:600px; @@ -75,11 +69,9 @@ h2 { color : black; } - - - .page_footer { height:190px; background: #b0b0b0; text-align : center; -} \ No newline at end of file +} + diff --git a/src/component/LoginPage2.module.css b/src/component/LoginPage2.module.css index f8a0f1c..3e1dd68 100644 --- a/src/component/LoginPage2.module.css +++ b/src/component/LoginPage2.module.css @@ -16,14 +16,8 @@ } span { font-size:18px; - margin-right:25px; + /*margin-right:25px;*/ } -span:hover { - color: black; -} - - - .page_middle { height:600px; @@ -53,18 +47,23 @@ span:hover { margin-bottom : 20px; width: 100%; height : 40px; + /*background-color : #1677ff;*/ + /*color : white;*/ } +/*.login_form_button:hover {*/ +/* background-color : #69b1ff; */ +/*}*/ + .login_form_register { font-size : 20px; } - - - - - +.login_error { + font-size : 15px; + color : red; +} .page_footer { height:190px; background: #b0b0b0; text-align : center; -} \ No newline at end of file +} diff --git a/src/component/LoginPageHeader.js b/src/component/LoginPageHeader.js new file mode 100644 index 0000000..5517d0d --- /dev/null +++ b/src/component/LoginPageHeader.js @@ -0,0 +1,30 @@ +import styles from "./LoginPageHeader.module.css"; +import {useNavigate} from "react-router-dom"; + + +const LoginPageHeader = (props) => { + const navigate = useNavigate(); + + const goRegisterPage = () => { + navigate('/account/Register'); + } + const goLoginPage = () => { + navigate('/account/Login'); + } + const goAccountPage = () => { + navigate('/account'); + } + return( +
+

Everything Of Container

+ +
+ + ) +} + +export default LoginPageHeader; diff --git a/src/component/LoginPageHeader.module.css b/src/component/LoginPageHeader.module.css new file mode 100644 index 0000000..2385e69 --- /dev/null +++ b/src/component/LoginPageHeader.module.css @@ -0,0 +1,30 @@ +.h1:hover { + cursor : pointer; +} + +.login_menu_tab { + margin-left : 25px; + margin-right : 25px; +} + +.login_menu:hover { + color : black; + cursor : pointer; +} + +.login_navigation { + margin-right : 30px; +} + +.page_header { + height:75px; + padding:1rem; + color:white; + background: #7F7FD5; + background: -webkit-linear-gradient(to right, #91EAE4, #86A8E7, #7F7FD5); + background: linear-gradient(to right, #91EAE4, #86A8E7, #7F7FD5); + font-weight:bold; + display:flex; + justify-content:space-between; + align-items:center; +} \ No newline at end of file diff --git a/src/component/Message.js b/src/component/Message.js deleted file mode 100644 index c4c5878..0000000 --- a/src/component/Message.js +++ /dev/null @@ -1,8 +0,0 @@ -const Message = (props) => { - return( -
-

메세지가 들어갈 부분입니다.

-
- ) -} -export default Message; \ No newline at end of file diff --git a/src/component/Navigation.css b/src/component/Navigation.css index c253eda..83eea50 100644 --- a/src/component/Navigation.css +++ b/src/component/Navigation.css @@ -1,8 +1,21 @@ -.logo{ - float: left; - width: 150px; - font-weight: bold; - font-size: 15px; - color : blue; - margin-left: 10px; +.login_menu { + margin-left: 15px; + margin-right: 15px; + /*텍스트굵게*/ +} + + +.signup_menu { + margin-left: 15px; + margin-right : 50px; +} + +.login_menu:hover { + color: black; + cursor:pointer; +} + +.signup_menu:hover { + color: black; + cursor: pointer; } \ No newline at end of file diff --git a/src/component/Navigation.js b/src/component/Navigation.js index 5d0f496..6cf0a91 100644 --- a/src/component/Navigation.js +++ b/src/component/Navigation.js @@ -1,14 +1,13 @@ import {Menu} from "antd"; import {useState} from "react"; -import "./Navigation.css" import {useNavigate} from "react-router-dom"; +import './Navigation.css'; const Navigation = (props) => { const navigate = useNavigate(); const items = [ {key: 'data-manage', label: '적재데이터관리'}, - {key: 'order-manage', label: '상품주문관리'}, - {key: 'part-3', label: '적재결과관리'}, + {key: 'load-result-manage', label: '적재결과관리'}, ] const [current, setCurrent] = useState('mail'); const onClick = (e) => { @@ -17,9 +16,28 @@ const Navigation = (props) => { setCurrent(e.key); }; + const goRegisterPage = () => { + navigate('./account/Register'); + } + const goLoginPage = () => { + navigate('./account/Login'); + } + + const navStyle = { + textAlign : 'right', + backgroundColor: '#abcdef', + color : 'white', + textStyle: 'bold', + } + + return (
-
컨테이너의 모든것
+
) diff --git a/src/component/NavigationForUser.js b/src/component/NavigationForUser.js new file mode 100644 index 0000000..5966471 --- /dev/null +++ b/src/component/NavigationForUser.js @@ -0,0 +1,45 @@ +import {Menu} from "antd"; +import {useState} from "react"; +import {useNavigate} from "react-router-dom"; +import './Navigation.css'; + +const Navigation = (props) => { + const navigate = useNavigate(); + const items = [ + {key: 'goods-register', label: '상품등록'}, + {key: 'order-delivery', label: '주문/배송'}, + ] + const [click, setClick] = useState('mail'); + const onClick = (e) => { + console.log('click ', e); + navigate(`${e.key}`); + setClick(e.key); + }; + + const goRegisterPage = () => { + navigate('../account/Register'); + } + const goLoginPage = () => { + navigate('../account/Login'); + } + + const navStyle = { + textAlign : 'right', + backgroundColor: '#abcdef', + color : 'white', + textStyle: 'bold', + } + + return ( +
+ + +
+ ) +} + +export default Navigation \ No newline at end of file diff --git a/src/component/RegisterPage.module.css b/src/component/RegisterPage.module.css index c9aeb75..fd5de9e 100644 --- a/src/component/RegisterPage.module.css +++ b/src/component/RegisterPage.module.css @@ -16,20 +16,19 @@ } span { font-size:18px; - margin-right:25px; + /*margin-right:25px;*/ } -span:hover { - color: black; -} + .font_style { font-size:20px; - } - - +.register_form { + margin-left:70px; + max-width:700px; +} .page_middle { height:1100px; display:flex; @@ -38,8 +37,8 @@ span:hover { } .middle_register { background:white; - width:900px; - height:1000px; + width:800px; + height:1050px; border:1px solid #909090; border-radius:20px; float:left; @@ -51,18 +50,34 @@ span:hover { .middle_register_button { float:left; margin-left:320px; - } .middle_register_button_1 { text-align: center; + margin-right:10px; } .middle_register_button_2 { text-align: center; } +.idCheck { + margin-top:15px; + margin-right:30px; + width:170px; + background-color : #1677ff; + color : white; + +} +.idCheck:hover { + background : white; + color : white; +} +.address_style { + width:250px; +} + .page_footer { height:190px; background: #b0b0b0; text-align : center; -} \ No newline at end of file +} diff --git a/src/page/MainPageLayout.js b/src/page/MainPageLayout.js index 779a473..7f76ee5 100644 --- a/src/page/MainPageLayout.js +++ b/src/page/MainPageLayout.js @@ -1,39 +1,32 @@ import {Layout} from "antd"; import Navigation from "../component/Navigation"; -import Message from "../component/Message"; -import { Outlet } from "react-router" -import { Routes, Route} from "react-router-dom"; -import DataManage from "./manager/DataManage"; +import { Outlet } from "react-router"; +import {useNavigate} from "react-router-dom"; -const {Header, Footer} = Layout; +const {Header} = Layout; const headerStyle = { - textAlign: 'right', - color: '#000', - paddingInline: 50, - backgroundColor: '#fff', + textAlign: 'left', + color: '#fff', + backgroundColor: '#abcdef', }; -const footerStyle = { - textAlign: 'center', - color: '#000', - backgroundColor: '#fff', -}; const MainPageLayout = (props) => { + const navigate = useNavigate(); + const goMainPage = () => { + navigate('./'); + } + return (
- +

Everything of Container

- + - -
) } diff --git a/src/page/MainPageLayoutForUser.js b/src/page/MainPageLayoutForUser.js new file mode 100644 index 0000000..3916aa3 --- /dev/null +++ b/src/page/MainPageLayoutForUser.js @@ -0,0 +1,32 @@ +import {Layout, Menu} from "antd"; +import { Outlet } from "react-router"; +import {useNavigate} from "react-router-dom"; +import NavigationForUser from "../component/NavigationForUser"; + +const {Header} = Layout; + +const headerStyle = { + textAlign: 'left', + color: '#fff', + backgroundColor: '#abcdef', +}; + +const MainPageLayoutForUser = (props) => { + const navigate = useNavigate(); + const goMainPageForUser = () => { + navigate('.'); + } + + return ( + +
+

Everything of Container

+
+ + + + +
+ ) +} +export default MainPageLayoutForUser; \ No newline at end of file diff --git a/src/page/login/CheckDupId.js b/src/page/login/CheckDupId.js new file mode 100644 index 0000000..892f4f1 --- /dev/null +++ b/src/page/login/CheckDupId.js @@ -0,0 +1,43 @@ +import React, { useState,useEffect } from 'react'; +import styles from "../../component/CheckDupId.module.css"; +import {Content} from "antd/es/layout/layout"; +import {Button,Form,Input} from 'antd'; +import axios from "axios"; +import {useNavigate} from "react-router-dom"; + + +const CheckDupId = () => { + const [userId,setUserId] = useState(''); + const navigate = useNavigate(); + + const handleCheck = async () => { + try { + let result = (await axios.get("http://localhost:8080/account/signup/{userId}")); + if (result.status == 200) { + alert('사용 가능한 아이디입니다.'); + } + navigate("../../"); + + } catch (e) { + alert('중복된 아이디입니다.'); + } + } + + return ( + +

아이디 중복 검사

+
+
+ + { setUserId(e.target.value); }}/> + + + + +
+
+
+ ); +}; + +export default CheckDupId; diff --git a/src/page/login/FindAddress.js b/src/page/login/FindAddress.js new file mode 100644 index 0000000..4b315fb --- /dev/null +++ b/src/page/login/FindAddress.js @@ -0,0 +1,18 @@ +import React, { useState } from 'react'; +import {Form} from 'antd'; + + + + +const Upload = () => { + + return ( +
+ + +
+ + ); +}; + +export default Upload; diff --git a/src/page/login/LoginPage.js b/src/page/login/LoginPage.js index dfbc28d..417ab7b 100644 --- a/src/page/login/LoginPage.js +++ b/src/page/login/LoginPage.js @@ -3,7 +3,7 @@ import styles from "../../component/LoginPage.module.css"; import {useNavigate} from "react-router-dom"; import user_login from "../../user-login.png"; import user_register from "../../user-register.png"; - +import LoginPageHeader from "../../component/LoginPageHeader"; const LoginPage = (props) => { const navigate = useNavigate(); @@ -17,19 +17,14 @@ const LoginPage = (props) => { const goAccountPage = () => { navigate('../account'); } + const goMainPage = () => { + navigate('../'); + } return (
-
-

Everything Of Container

- -
- +
@@ -49,4 +44,4 @@ const LoginPage = (props) => { ) } -export default LoginPage; \ No newline at end of file +export default LoginPage; diff --git a/src/page/login/LoginPage2.js b/src/page/login/LoginPage2.js index efacffc..dc77d3a 100644 --- a/src/page/login/LoginPage2.js +++ b/src/page/login/LoginPage2.js @@ -1,60 +1,92 @@ import {Content} from "antd/es/layout/layout"; import styles from "../../component/LoginPage2.module.css"; import { LockOutlined, UserOutlined } from "@ant-design/icons"; -import {useNavigate} from "react-router-dom"; import {Form,Input,Checkbox,Button,Radio} from "antd"; import React, {useState} from 'react'; +import LoginPageHeader from "../../component/LoginPageHeader"; +import axios from 'axios'; +import {useNavigate} from "react-router-dom"; const LoginPage2 = (props) => { + const [userId,setUserId] = useState(''); + const [password,setPassword] = useState(''); + const [authority,setAuthority] = useState('0'); + const [msg,setMsg] = useState(''); const navigate = useNavigate(); + const signInRequest = { + "userId" : userId, + "password" : password + }; + - const goRegisterPage = () => { - navigate('../account/Register'); - } - const goLoginPage = () => { - navigate('../account/Login'); - } - const goAccountPage = () => { - navigate('../account'); - } + const loginUser = async () => { + if (authority == 0 && userId.length != 0 && password.length != 0) { + setMsg('관리자 또는 사용자를 체크해주세요.'); + } + else if (userId.length == 0 && password.length != 0) { + setMsg('아이디는 필수 입력사항입니다.'); + } + else if (userId.length != 0 && password.length == 0) { + setMsg('비밀번호는 필수 입력사항입니다.'); + } + else if (userId.length == 0 && password.length == 0) { + setMsg('회원이 아니신 경우 회원가입을 눌러주세요.'); + } + else { + setMsg(''); + try { + let result = (await axios.post("http://localhost:8080/account/signin",signInRequest)); + if(result.status ===200){ + localStorage.setItem("accessToken", result.data.accessToken) + localStorage.setItem("refreshToken", result.data.refreshToken) + + if(authority == '1') { + navigate('../../'); + } + if(authority == '2') { + navigate('../../user'); + } + } + + } catch (e) { + setMsg('정보를 올바르게 입력해주세요.'); + } + }; + } return (
-
-

Everything Of Container

- -
+
-
+ - 관리자 - 사용자 + { setAuthority('1')}}>관리자 + { setAuthority('2') }}>사용자 - - } placeholder={"아이디를 입력하세요."}/> + + } onChange={(e) => { setUserId(e.target.value); }} value={userId} placeholder={"아이디를 입력하세요."}/> - - }placeholder={"비밀번호를 입력하세요."}/> + + } onChange={(e) => { setPassword(e.target.value); }} value={password} placeholder={"비밀번호를 입력하세요."}/> 아이디 자동저장 - - Or 회원가입 + + 회원가입 + + + {msg}
diff --git a/src/page/login/Register.js b/src/page/login/Register.js index 6d336ae..0825797 100644 --- a/src/page/login/Register.js +++ b/src/page/login/Register.js @@ -1,26 +1,61 @@ import {Content} from "antd/es/layout/layout"; import styles from "../../component/RegisterPage.module.css"; -import {useNavigate} from "react-router-dom"; import {Form,Input,Radio,Select,Button} from "antd"; -import React, {useState} from 'react'; +import React, {useState,useCallback} from 'react'; +import useInput from './useInput'; +import LoginPageHeader from "../../component/LoginPageHeader"; +import {useDaumPostcodePopup} from "react-daum-postcode"; +import axios from 'axios'; +import {useNavigate} from "react-router-dom"; const { Option }= Select; const Register = (props) => { + const scriptUrl = "//t1.daumcdn.net/mapjsapi/bundle/postcode/prod/postcode.v2.js"; + const navigate = useNavigate(); + const open = useDaumPostcodePopup(scriptUrl); + const [address,setAddress] = useState(''); + const [addr,setAddr] = useState(''); + const [extraAddress,setExtraAddress] = useState(''); + const [pwd, onChangePassword] = useInput(''); + const [number, onChangeNumber] = useInput(''); + const [msg,setMsg] = useState(''); + /*DB 연동*/ + const [userId,setUserId] = useState(''); + const [password,setPassword] = useState(''); + const [admCall,setAdmCall] = useState(''); + const [department,setDepartment] = useState(''); + const [position,setPosition] = useState(''); + const [facName,setFacName] = useState(''); + const [adName,setAdName] = useState(''); + const [rep,setRep] = useState(''); + const [location,setLocation] = useState(''); + const [role,setRole] = useState(''); + const signUpRequest = { + "userId": userId, + "password": password, + "admCall" : admCall, + "department" : department, + "position" : position, + "facName" : facName, + "adName" : adName, + "rep" : rep, + "location" : location, + "role" : role, + }; - const navigate = useNavigate(); - - const goRegisterPage = () => { - navigate('../account/Register'); - } - const goLoginPage = () => { - navigate('../account/Login'); - } - const goAccountPage = () => { - navigate('../account'); + const formItemLayout = { + labelCol: { + xs: { span: 24 }, + sm: { span: 4}, + }, + wrapperCol: { + xs: { span: 24 }, + sm: { span: 16 }, + } } const [admin_informDisabled, setAdmin_informDisabled] = useState (true); @@ -29,104 +64,193 @@ const Register = (props) => { const prefixSelector = ( ); + const checkId = async() => { + // console.log(value); + // window.open("/account/Register/checkDup","form","width=700, height=400, left=410, top=250"); + try { + let result = (await axios.get("http://localhost:8080/account/checkid/"+userId)) + + console.log(result); + if (result.status == 200) { + setMsg('사용가능한 아이디입니다.'); + } + } catch (e) { + setMsg('중복된 아이디입니다.'); + }; + }; + + + const moveAddress = (data) => { + let fullAddress = data.address; + let extraAddress = ''; + + if(data.addressType === 'R') { + if(data.bname !== '') { + extraAddress += data.bname; + } + if(data.buildingName !== '') { + extraAddress += extraAddress !== '' ? `, ${data.buildingName}` : data.buildingName; + } + fullAddress += extraAddress!== ''? `(${extraAddress})` : ''; + } + setAddress(data.zonecode); + setAddr(data.address); + setExtraAddress(extraAddress); + console.log(fullAddress); + }; + const handleClick= () => { + open({onComplete : moveAddress }); + }; + + const validatePassword = useCallback((_, value) => { + const regExp = /(?=.*\d{1,20})(?=.*[~`!@#$%\^&*()-+=]{1,20})(?=.*[a-z]{1,20}||[A-z]{1,20}).{5,20}$/; + if (!value) { + return Promise.reject(new Error('비밀번호는 필수 항목입니다.')); + } + if (!regExp.test(value)) { + return Promise.reject(new Error('비밀번호는 5~20자이며 영문, 숫자, 특수문자를 모두 포함해야 합니다.')); + } + return Promise.resolve(); + }, []); + + const validateNumber = useCallback((_,value) => { + const phnExp = /(?=.*\d{1,8}).{8}$/; + if (!value) { + return Promise.reject(new Error('전화번호는 필수 항목입니다.')); + } + if(value.length > 8) { + return Promise.reject(new Error('전화번호는 -를 제외한 8자리 숫자를 입력해야 합니다.')); + } + if (!phnExp.test(value)) { + return Promise.reject(new Error('전화번호는 -를 제외한 8자리 숫자를 입력해야 합니다.')); + } + if(phnExp.test(value)) { + setAdmCall (value); + } + return Promise.resolve(); + }, []); + + const registerUser = async () => { + console.log(signUpRequest); + + try { + let result = (await axios.post("http://localhost:8080/account/signup",signUpRequest)); + if (result.status == 200) { + console.log(result); + localStorage.setItem("accessToken", result.data.accessToken) + localStorage.setItem("refreshToken", result.data.refreshToken) + + alert('회원가입 되었습니다.'); + navigate('../account'); + } + } catch (e) { + alert('회원정보를 올바르게 입력해주세요.'); + } + }; return ( - +
-
-

Everything Of Container

- -
+

공통 정보 입력

- + - {setAdmin_informDisabled(false);setUser_informDisabled(true)}}>관리자입니다. - {setAdmin_informDisabled(true);setUser_informDisabled(false)}}>사용자입니다. + {setAdmin_informDisabled(false);setUser_informDisabled(true); setRole('ROLE_ADMIN')}}>관리자입니다. + {setAdmin_informDisabled(true);setUser_informDisabled(false); setRole('ROLE_USER')}}>사용자입니다. - + { setUserId(e.target.value); }} value={userId}/> + + {msg} - - - 8~16자 영문 대 소문자,숫자,특수문자를 사용하세요. + + - ({ - validator(_, value) { - if (getFieldValue("password") === value) { - return Promise.resolve(); - } - return Promise.reject(new Error('The two passwords that you entered do not match!')); + - + ({ getFieldValue }) => ({ + validator(_, value) { + if (!value || getFieldValue('password') === value) { + return Promise.resolve(); + } + return Promise.reject(new Error('입력한 비밀번호와 일치하지 않습니다.')); + }, + }), + ]} + > + { setPassword(e.target.value); }} value={password}/> - - + + + + +
+

관리자 정보 입력

+
+ + { setAdName(e.target.value); }}/> -
- -

관리자 정보 입력

- - - - - - - - - - -
-
- -

사용자 정보 입력

-
- - - - - - - - - -
- - - + + { setDepartment(e.target.value); }}/> + + + { setPosition(e.target.value); }}/> +
+

사용자 정보 입력

+
+ + + + + +
+ + +
+ + { setLocation(e.target.value); }}/> +
+
+ + { setFacName(e.target.value); }}/> + + + { setRep(e.target.value); }}/> + + + + + +
+ +

컨테이너의 모든 것

-
- + ) } diff --git a/src/page/login/useInput.js b/src/page/login/useInput.js new file mode 100644 index 0000000..4b1ef5a --- /dev/null +++ b/src/page/login/useInput.js @@ -0,0 +1,10 @@ +import {useCallback, useState} from "react"; + +export default (initialValue = null) => { + const [value, setValue] = useState(initialValue); + const handler = useCallback((e) => { + setValue(e.target.value); + }, []); + + return [value, handler, setValue]; +}; \ No newline at end of file diff --git a/src/page/manager/DataManage.css b/src/page/manager/DataManage.css index e18d91b..78d1155 100644 --- a/src/page/manager/DataManage.css +++ b/src/page/manager/DataManage.css @@ -1,9 +1,21 @@ .search { - width : 150px; - margin-top : 60px; + width: 170px; + margin-top: 50px; + margin-left: 10px; } - .button { margin-top : 10px; - height : 30px; -} \ No newline at end of file + height : 40px; + width: 100px; +} + +.upload { + margin-left : 60px; + margin-top: 30px; +} + +.submit { + margin-left: 30px; + margin-top : 30px; + +} diff --git a/src/page/manager/DataManage.js b/src/page/manager/DataManage.js index a3aa62c..57b6953 100644 --- a/src/page/manager/DataManage.js +++ b/src/page/manager/DataManage.js @@ -1,29 +1,12 @@ -import {Anchor, Layout, Table, Tabs} from "antd"; +import {Layout, Table, Tabs} from "antd"; import Sider from "antd/es/layout/Sider"; import {Content} from "antd/es/layout/layout"; -import axios from "axios"; -import {useEffect, useState} from "react"; -import { AudioOutlined } from '@ant-design/icons'; -import { Input, Space, Button } from 'antd'; +import {createRef, useState} from "react"; import './DataManage.css'; +import DataManageTabControl from "./DataManageTabControl"; +import ContainerTab from "./container/ContainerTab"; +import PaletteTab from "./palette/PaletteTab"; - -const { Search } = Input; -const suffix = ( - -); -const onSearch = (value) => { - console.log(value) -}; -const onClick = (value) => { - console.log(value) - window.open("/", "a", "width=400, height=300, left=100, top=50"); // 팝업 띄우기 -}; const contentStyle = { textAlign: 'center', minHeight: 120, @@ -38,90 +21,25 @@ const siderStyle = { }; const DataManage = (props) => { - const onChange = (key) => { - console.log(key); - }; + const [currentTab, setCurrentTab] = useState('container') + const containerRef = createRef(); + const paletteRef = createRef(); + const items = [ - {key: 'container', label: `컨테이너 관리`, children: ,}, - {key: 'pallete', label: `팔레트 관리`, children: ,} + {key: 'container', label: `컨테이너 관리`, children: ,}, + {key: 'palette', label: `팔레트 관리`, children: ,} ]; + return ( - - + - - + ) } -const ContainerManage = (props) => { - const [containers, setContainers] = useState([ - - ]); - - useEffect(()=>{ - getContainerData() - },[]) - - const columns = [ - {title: '컨테이너ID', dataIndex: 'id', key: 'id',}, - {title: '가로(m)', dataIndex: 'width', key: 'width',}, - {title: '세로(m)', dataIndex: 'depth', key: 'depth',}, - {title: '높이(m)', dataIndex: 'height', key: 'height',}, - {title: '부피(m^3)', dataIndex: 'volume', key: 'volume',}, - {title: '무게(kg)', dataIndex: 'weight', key: 'weight',}, - {title: '무게제한(kg)', dataIndex: 'weightlimit', key: 'weightlimit',}, - {title: '출고마감시간', dataIndex: 'deadline', key: 'deadline',}, - ]; - - - const getContainerData = async ()=>{ - let result = (await axios.get("http://localhost:8080/api/container")).data - setContainers(result) - } - - return ( -
- - - ) -} - -const PalleteManage = (props) => { - const [pallete, setPallete] = useState([ - - ]); - - useEffect(()=>{ - getPalleteData() - },[]) - - const columns = [ - {title: '팔레트ID', dataIndex: 'id', key: 'id',}, - {title: '상품명', dataIndex: 'name', key: 'name',}, - {title: '수량(개)', dataIndex: 'count', key: 'count',}, - {title: '가로(m)', dataIndex: 'width', key: 'width',}, - {title: '세로(m)', dataIndex: 'depth', key: 'depth',}, - {title: '높이(m)', dataIndex: 'height', key: 'height',}, - {title: '부피(m^3)', dataIndex: 'volume', key: 'volume',}, - {title: '무게(kg)', dataIndex: 'weight', key: 'weight',}, - ]; - - const getPalleteData = async ()=>{ - let result = (await axios.get("http://localhost:8080/api/palette")).data - setPallete(result) - } - - return ( -
-
- - ) -} - export default DataManage; \ No newline at end of file diff --git a/src/page/manager/DataManageTabControl.js b/src/page/manager/DataManageTabControl.js new file mode 100644 index 0000000..eeb6edb --- /dev/null +++ b/src/page/manager/DataManageTabControl.js @@ -0,0 +1,11 @@ +import ContainerTabControl from "./container/ContainerTabControl"; +import PaletteTabControl from "./palette/PaletteTabControl"; + +const DataManageTabControl = (props) => { + if (props.tab === 'container') + return () + else if (props.tab === 'palette') + return () +} + +export default DataManageTabControl \ No newline at end of file diff --git a/src/page/manager/LoadResultManage.css b/src/page/manager/LoadResultManage.css new file mode 100644 index 0000000..bb4e78f --- /dev/null +++ b/src/page/manager/LoadResultManage.css @@ -0,0 +1,38 @@ +.containerButton { + border: 1px solid skyblue; + background-color: #abcdef; + color: white; + border-radius: 10px; + width: 150px; + height: 60px; + font-size: 18px; + transition: transform 0.2s; +} + +.containerButton:active { + transform: scale(0.90); + box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.3); +} +.containerButton:hover { + background-color: #86A8E7; +} +.palletButton { + border: 1px solid skyblue; + background-color: #abcdef; + color: white; + border-radius: 10px; + width: 150px; + height: 60px; + font-size: 18px; + transition: transform 0.2s; +} +.palletButton:active { + transform: scale(0.90); + box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.3); +} +.palletButton:hover { + background-color: #86A8E7; +} +.tl { + height: 60px; +} \ No newline at end of file diff --git a/src/page/manager/LoadResultManage.js b/src/page/manager/LoadResultManage.js new file mode 100644 index 0000000..9473b52 --- /dev/null +++ b/src/page/manager/LoadResultManage.js @@ -0,0 +1,472 @@ +import {Anchor, Badge, Dropdown, Layout, Space, Table, Tabs} from "antd"; +import Sider from "antd/es/layout/Sider"; +import {Content} from "antd/es/layout/layout"; +import axios from "axios"; +import {useEffect, useRef, useState} from "react"; +import Search from "antd/es/input/Search"; +import './DataManage.css'; +import * as THREE from "three"; +import { OrbitControls } from "three/examples/jsm/controls/OrbitControls"; +import './LoadResultManage.css'; +import SetPallet from "./SetPallet"; +import {WebGLRenderList as cubeControls} from "three/src/renderers/webgl/WebGLRenderLists"; +import { TransformControls } from "three/addons/controls/TransformControls"; +import {DownOutlined} from "@ant-design/icons"; + + +const LoadResultManage = () => { + const containerSize = { width: 2.4, height: 2.4, depth: 5.9 }; + const palletEx = { width: containerSize.width / 2, height: 0.2, depth: containerSize.depth }; + const palletTypeA = { id: 'typeA', width: 1.1, height: 0.8, depth: 1.1 }; + const palletTypeB = { id: 'typeB', width: 1.1, height: 1.0, depth: 1.1}; + const palletTypeC = { id: 'typeC', width: 1.1, height: 1.5, depth: 1.1}; + const mountRef = useRef(null); + const [scene, setScene] = useState(null); + const [renderer, setRenderer] = useState(null); + const [camera, setCamera] = useState(null); + const [controls, setControls] = useState(null); + const [pallets, setPallets] = useState([]); + const [tablePallets, setTablePallets] = useState(new Map()); + + + const getContainerData = async ()=>{ + let result = (await axios.get("http://localhost:8080/container", + { + headers: {Authorization: `Bearer ${localStorage.getItem('accessToken')}`,}, + })).data + console.log(result) + setContainers(result) + } + + const [containers, setContainers] = useState([ + // {containerSearch: '1', paletteSearch: '1', paletteInfo: '아이시스 2L 6개묶음, 20, 2023-05-31 22:30, 2023-06-02 14:30', }, + // {containerSearch: '', paletteSearch: '2', paletteInfo: '대림선 야채 김자반볶음 1+1 기획, 500, 2023-05-31 22:30, 2023-06-03 15:30', }, + // {containerSearch: '', paletteSearch: '3', paletteInfo: '삼성갤럭시Z플립3, 100, 2023-05-31 22:30 2023-06-03 16:40',}, + ]); + + const columns = [ + {title: '▼ 컨테이너 ID', dataIndex: 'containerId', key: 'containerId',}, + // {title: '▼ 팔레트 조회', dataIndex: 'paletteSearch', key: 'paletteSearch',}, + // {title: '▼ 팔레트 실제 정보 (상품명, 주문개수, 주문일자, 출고마감시간)', dataIndex: 'paletteInfo', key: 'paletteInfo',}, + + ]; + + useEffect(() => { + getContainerData() + const scene = new THREE.Scene(); + setScene(scene); + scene.background = new THREE.Color(0xFFFFFF); + + const renderer = new THREE.WebGLRenderer(); + setRenderer(renderer); + + const camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 0.1, 1000); + + const orbitControls = new OrbitControls(camera, renderer.domElement); + orbitControls.enabled = false; + scene.add(orbitControls); + const moveContainerButton = document.getElementById('moveContainerButton'); + moveContainerButton.addEventListener('click', () => { + if (orbitControls) { + orbitControls.enabled = !orbitControls.enabled; + } + }); + + camera.position.set(8, 8, 8); + camera.lookAt(new THREE.Vector3(1, 0, 2)); + setCamera(camera); + + /*const controls = new OrbitControls(camera, renderer.domElement); + setControls(controls);*/ + + + const mount = mountRef.current; + mount.appendChild(renderer.domElement); + renderer.setSize(mount.clientWidth, mount.clientHeight); + + const animate = function () { + requestAnimationFrame(animate); + /*controls.update();*/ + renderer.render(scene, camera); + }; + + animate(); + + const handleResize = () => { + const width = mount.clientWidth; + const height = mount.clientHeight; + + renderer.setSize(width, height); + camera.aspect = width / height; + camera.updateProjectionMatrix(); + }; + + window.addEventListener('resize', handleResize); + + const containerCube = createCube(containerSize.width, containerSize.height, containerSize.depth); + scene.add(containerCube); + containerCube.position.set(0, 0, 0); + + return () => { + window.removeEventListener('resize', handleResize); + mount.removeChild(renderer.domElement); + }; + + }, []); + + const moveButton = document.getElementById('moveButton'); + const deleteButton=document.getElementById('deleteButton'); + + + function addPalletA() { + const geometry = new THREE.BoxGeometry(palletTypeA.width, palletTypeA.height, palletTypeA.depth); + const material = new THREE.MeshBasicMaterial({ color: 'skyblue' }); + const cube = new THREE.Mesh(geometry, material); + + const offsetX = palletTypeA.width / 2; + const offsetY = palletTypeA.height / 2; + const offsetZ = palletTypeA.depth / 2; + + const minX = offsetX; + const maxX = containerSize.width - offsetX; + const minZ = offsetZ; + const maxZ = containerSize.depth - offsetZ; + + + const randomX = Math.random() * (maxX - minX) + minX; + const randomZ = Math.random() * (maxZ - minZ) + minZ; + + cube.position.set(randomX, offsetY, randomZ); + scene.add(cube); + + + const controls = new TransformControls(camera, renderer.domElement); + cube.controls=controls; + controls.attach(cube); + scene.add(controls); + + + controls.setMode('translate'); + controls.setSpace('local'); + controls.showY = !controls.showY; + + + moveButton.addEventListener('click', () => { + if (controls.enabled) { + controls.detach(); + controls.enabled = false; + } else { + controls.attach(cube); + controls.enabled = true; + } + }); + + setPallets(pallets => [...pallets, cube]); + controls.visible = false; + + + } + + function addPalletB() { + const geometry = new THREE.BoxGeometry(palletTypeB.width, palletTypeB.height, palletTypeB.depth); + const material = new THREE.MeshBasicMaterial({ color: 'yellow' }); + const cube = new THREE.Mesh(geometry, material); + + const offsetX = palletTypeB.width / 2; + const offsetY = palletTypeB.height / 2; + const offsetZ = palletTypeB.depth / 2; + + const minX = offsetX; + const maxX = containerSize.width - offsetX; + const minZ = offsetZ; + const maxZ = containerSize.depth - offsetZ; + + const randomX = Math.random() * (maxX - minX) + minX; + const randomZ = Math.random() * (maxZ - minZ) + minZ; + + cube.position.set(randomX, offsetY, randomZ); + scene.add(cube); + + + const controls = new TransformControls(camera, renderer.domElement); + cube.controls=controls; + controls.attach(cube); + scene.add(controls); + controls.showY = !controls.showY; + + + controls.setMode('translate'); + controls.setSpace('local'); + + + moveButton.addEventListener('click', () => { + if (controls.enabled) { + controls.detach(); + controls.enabled = false; + } else { + controls.attach(cube); + controls.enabled = true; + } + }); + + setPallets(pallets => [...pallets, cube]); + controls.visible = false; + + } + + function addPalletC() { + const geometry = new THREE.BoxGeometry(palletTypeC.width, palletTypeC.height, palletTypeC.depth); + const material = new THREE.MeshBasicMaterial({ color: 'pink' }); + const cube = new THREE.Mesh(geometry, material); + + const offsetX = palletTypeC.width / 2; + const offsetY = palletTypeC.height / 2; + const offsetZ = palletTypeC.depth / 2; + + const minX = offsetX; + const maxX = containerSize.width - offsetX; + const minZ = offsetZ; + const maxZ = containerSize.depth - offsetZ; + + const randomX = Math.random() * (maxX - minX) + minX; + const randomZ = Math.random() * (maxZ - minZ) + minZ; + + cube.position.set(randomX, offsetY, randomZ); + scene.add(cube); + + const controls = new TransformControls(camera, renderer.domElement); + cube.controls=controls; + controls.attach(cube); + scene.add(controls); + controls.showY = !controls.showY; + + controls.setMode('translate'); + controls.setSpace('local'); + + moveButton.addEventListener('click', () => { + if (controls.enabled) { + controls.detach(); + controls.enabled = false; + } else { + controls.attach(cube); + controls.enabled = true; + } + }); + + setPallets(pallets => [...pallets, cube]); + controls.visible = false; + + } + + function onClick2() { + if (pallets.length > 0) { + const lastCube = pallets[pallets.length - 1]; + const controls = lastCube.controls; + + if (controls) { + controls.visible=false; + controls.detach(); + controls.dispose(); + scene.remove(controls); + } + scene.remove(lastCube); + setPallets(pallets => pallets.filter(cube => cube !== lastCube)); + } + } + const onClick1 = () => { + /*const newWindow = window.open("/MovePallet", "a", "width=700, height=400, left=100, top=50"); + + newWindow.onload = () => { + const buttons = newWindow.document.querySelectorAll("button"); + + + };*/ + }; + + const onClick3=()=> { + + } + + function sleep(sec) { + return new Promise(resolve => setTimeout(resolve, sec * 1000)); + } + const onClick4 = () => { + const newWindow = window.open("/SetPallet", "_blank", "width=700, height=400, left=100, top=50"); + console.log(newWindow) + + newWindow.addEventListener('load', async () => { + const buttons = await newWindow.document.getElementsByClassName("containerButton"); + await sleep(1) + + const handleClick = (event) => { + const buttonId = event.target.id; + + if (buttonId === 'palletTypeA') { + addPalletA(); + } + else if (buttonId === 'palletTypeB') { + addPalletB(); + } + else if (buttonId === 'palletTypeC') { + addPalletC(); + } + else if (buttonId==='setPalletWindowquit') { + newWindow.close(); + } + }; + + Array.from(buttons).forEach((button) => { + console.log("handleClickMapping") + button.addEventListener("click", handleClick); + }); + + newWindow.onbeforeunload = () => { + Array.from(buttons).forEach((button) => { + console.log("unmapping handleClick") + button.removeEventListener("click", handleClick); + }); + }; + } + ) + }; + + + const expandedRowRender = (record, index) => { + const columns = [ + { + title: '팔레트ID', + dataIndex: 'paletteId', + key: 'paletteId', + }, + { + title: '상품명', + dataIndex: 'paletteName', + key: 'paletteName', + }, + { + title: '주문개수', + dataIndex: 'quantity', + key: 'quantity', + }, + { + title: '출고마감시간', + dataIndex: 'deadLine', + key: 'deadLine', + }, + ]; + + return
; + }; + + const onExpand = (expanded, record) =>{ + axios.get(`http://localhost:8080/palette?containerId=${record.containerId}`, + { + headers: {Authorization: `Bearer ${localStorage.getItem('accessToken')}`,}, + }) + .then(res => { + setTablePallets((prev) => new Map(prev).set(record.containerId, res.data)); + } + ) + + } + + return ( + +
+ + +
▼        컨테이너 내 팔레트 실시간 적재 현황
+
+
+ +
+ + + + +
+
+
+
+
+ {/*
*/} + {/*
*/} + {/**/} + + + + + + ); +} +function createCube(width, height, depth) { + const vertices = [ + [0, height, depth], + [width, height, depth], + [width, height, 0], + [0, height, 0], + [0, 0, depth], + [width, 0, depth], + [width, 0, 0], + [0, 0, 0], + ]; + + const indices = [ + 0, 1, 1, 2, 2, 3, 3, 0, + 4, 5, 5, 6, 6, 7, 7, 4, + 0, 4, 1, 5, 2, 6, 3, 7, + ]; + + const geometry = new THREE.BufferGeometry(); + const positionNumComponents = 3; + const positions = new Float32Array(vertices.flat()); + geometry.setAttribute( + "position", + new THREE.BufferAttribute(positions, positionNumComponents) + ); + geometry.setIndex(indices); + + const material = new THREE.LineBasicMaterial({ color: 0x000000 }); + const cube = new THREE.LineSegments(geometry, material); + + return cube; +} + +const contentStyle = { + textAlign: 'center', + minHeight: 120, + lineHeight: '120px', + backgroundColor: '#fff', + + +}; +const siderStyle = { + textAlign: 'right', + lineHeight: '120px', + color: '#fff', + backgroundColor: '#fff', + borderRight: "1px solid #CCC", + height: '580px', + border: '1px solid black' +}; + +const onSearch = (value) => { + console.log(value) +}; + +const onClick4 = (value) => { + console.log(value); + window.open("/SetPallet", "a", "width=1200, height=600, left=100, top=50"); // 팝업 띄우기 +}; + +export default LoadResultManage; \ No newline at end of file diff --git a/src/page/manager/Mapping.js b/src/page/manager/Mapping.js new file mode 100644 index 0000000..ed2a2f0 --- /dev/null +++ b/src/page/manager/Mapping.js @@ -0,0 +1,52 @@ +import React from 'react'; +import { + Button, + Form, + InputNumber, + +} from 'antd'; + +import axios from "axios"; + +const Mapping = () => { + const [newContainer] = Form.useForm() + const registerContainer = async () => { + let formValue + let canRegister = false + try { + formValue = await newContainer.validateFields() + canRegister = true + } catch (e) { + alert('필수값은 모두 입력하여야합니다.') + } + if(!canRegister) return + try { + let result = (await axios.put(`http://localhost:8080/palette/${formValue.paletteId}/container/${formValue.containerId}`,{}, + { + headers: {Authorization: `Bearer ${localStorage.getItem('accessToken')}`,}, + })); + if(result.status === 200 ) { + alert('매핑되었습니다.') + } + } catch(e){ + alert('매핑 실패하였습니다.') + } + } + return ( + + + + + + + + + + + + + + ); +}; + +export default Mapping; diff --git a/src/page/manager/OrderManage.js b/src/page/manager/OrderManage.js deleted file mode 100644 index ae0febc..0000000 --- a/src/page/manager/OrderManage.js +++ /dev/null @@ -1,55 +0,0 @@ -import {Anchor, Layout, Table, Tabs} from "antd"; -import Sider from "antd/es/layout/Sider"; -import {Content} from "antd/es/layout/layout"; -import axios from "axios"; -import {useEffect, useState} from "react"; - -const contentStyle = { - textAlign: 'center', - minHeight: 120, - lineHeight: '120px', - backgroundColor: '#fff', -}; -const siderStyle = { - textAlign: 'center', - lineHeight: '120px', - color: '#fff', - backgroundColor: '#fff', -}; - -const OrderManage = (props) => { - const [orders, setOrders] = useState([ - {index: '1', orderNum: 2023, name: '삼성갤럭시Z플립4', count: 5, width: 32, depth: 10, height: 100, volume:1000, weight: 32000, }, - {index: '1', orderNum: 2023, name: '삼성갤럭시Z플립4', count: 5, width: 32, depth: 10, height: 100, volume:1000, weight: 32000, }, - {index: '1', orderNum: 2023, name: '삼성갤럭시Z플립4', count: 5, width: 32, depth: 10, height: 100, volume:1000, weight: 32000, }, - ]); - - useEffect(()=>{ - getOrderData() - },[]) - - const columns = [ - {title: '번호', dataIndex: 'index', key: 'index',}, - {title: '주문번호', dataIndex: 'orderNum', key: 'orderNum',}, - {title: '상품명', dataIndex: 'name', key: 'name',}, - {title: '수량(개)', dataIndex: 'count', key: 'count',}, - {title: '가로(m)', dataIndex: 'width', key: 'width',}, - {title: '세로(m)', dataIndex: 'depth', key: 'depth',}, - {title: '높이(m)', dataIndex: 'height', key: 'height',}, - {title: '부피(m^3)', dataIndex: 'volume', key: 'volume',}, - {title: '무게(kg)', dataIndex: 'weight', key: 'weight',}, - ]; - - - const getOrderData = async ()=>{ - let result = (await axios.get("http://localhost:8080/api/memo/{id}")).data - setOrders(result) - } - - return ( -
-
- - ) -} -export default OrderManage; \ No newline at end of file diff --git a/src/page/manager/SetPallet.js b/src/page/manager/SetPallet.js new file mode 100644 index 0000000..bd6a294 --- /dev/null +++ b/src/page/manager/SetPallet.js @@ -0,0 +1,56 @@ +import { + Button, + Cascader, + DatePicker, + Form, + Input, + InputNumber, + Radio, + Select, + Switch, + TreeSelect, +} from 'antd'; +import styles from "../../page/manager/DataManage.css"; +import React from "react"; +import './LoadResultManage.css'; + +const SetPallet = (/*{ ButtonA, ButtonB }*/) => { + const palletTypeA={ id:'typeA', width: 1.1, height: 0.8, depth:1.1}; + + return ( +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
Pallet Type가로 길이높이 길이세로 길이
1.10.81.1
1.11.01.1
1.11.51.1
+ + +
+
+ ); +}; + +export default SetPallet; \ No newline at end of file diff --git a/src/page/manager/Upload.js b/src/page/manager/Upload.js new file mode 100644 index 0000000..ec1cddc --- /dev/null +++ b/src/page/manager/Upload.js @@ -0,0 +1,57 @@ +import React, {useState} from 'react'; +import { + Button, + DatePicker, + Form, + InputNumber, + +} from 'antd'; +import styles from "../manager/DataManage.css"; +import axios from "axios"; + +const Upload = () => { + const [newContainer] = Form.useForm() + const registerContainer = async () => { + let createContainerRequest + let canRegister = false + try { + let formValue = await newContainer.validateFields() + createContainerRequest = {...formValue} + createContainerRequest.releaseDate = formValue.releaseDate.format().replace('+09:00', '') + canRegister = true + } catch (e) { + alert('필수값은 모두 입력하여야합니다.') + } + if(!canRegister) return + try { + let result = (await axios.post("http://localhost:8080/container",createContainerRequest, + { + headers: {Authorization: `Bearer ${localStorage.getItem('accessToken')}`,}, + })); + if(result.status === 200 ) { + alert('등록되었습니다.') + } + } catch(e){ + alert('등록 실패하였습니다.') + } + } + return ( +
+ + + + + + + + + + + + + +
+ ); +}; + +export default Upload; diff --git a/src/page/manager/container/ContainerTab.js b/src/page/manager/container/ContainerTab.js new file mode 100644 index 0000000..eff7072 --- /dev/null +++ b/src/page/manager/container/ContainerTab.js @@ -0,0 +1,49 @@ +import {forwardRef, useEffect, useImperativeHandle, useState} from "react"; +import axios from "axios"; +import {Table} from "antd"; + +const ContainerTab = forwardRef((props, ref) => { + const [containers, setContainers] = useState([]); + + const getContainerData = async ()=>{ + let result = (await axios.get("http://localhost:8080/container", + { + headers: {Authorization: `Bearer ${localStorage.getItem('accessToken')}`,}, + })).data + setContainers(result) + } + + useEffect(()=>{ + getContainerData() + },[]) + + + useImperativeHandle(ref, () => ({ + async search(searchParam){ + let result = (await axios.get(`http://localhost:8080/container`, { + params: searchParam, + headers: {Authorization: `Bearer ${localStorage.getItem('accessToken')}`,}, + })).data + setContainers(result) + } + })); + + const columns = [ + {title: '컨테이너ID', dataIndex: 'containerId', key: 'containerId',}, + {title: '가로(m)', dataIndex: 'width', key: 'width',}, + {title: '세로(m)', dataIndex: 'length', key: 'length',}, + {title: '높이(m)', dataIndex: 'height', key: 'height',}, + {title: '부피(m^3)', dataIndex: 'volume', key: 'volume',}, + {title: '무게(kg)', dataIndex: 'weight', key: 'weight',}, + {title: '무게제한(kg)', dataIndex: 'weightLimit', key: 'weightLimit',}, + {title: '출고마감시간', dataIndex: 'releaseDate', key: 'releaseDate',}, + ]; + + return ( +
+ + + ) +}) + +export default ContainerTab \ No newline at end of file diff --git a/src/page/manager/container/ContainerTabControl.js b/src/page/manager/container/ContainerTabControl.js new file mode 100644 index 0000000..a26d42c --- /dev/null +++ b/src/page/manager/container/ContainerTabControl.js @@ -0,0 +1,48 @@ +import {SearchOutlined} from '@ant-design/icons'; +import {Button, DatePicker, Form, InputNumber} from "antd"; + + +const ContainerTabControl = (props) => { + const [searchParam] = Form.useForm() + const createUpdate = () => { + window.open("/upload", "a", "width=500, height=700, left=100, top=50"); // =팝업 띄우기 + }; + + const createMapping = () => { + window.open("/mapping", "a", "width=600, height=200, left=100, top=50"); + } + + const onSearch = async () => { + let formValue = await searchParam.validateFields() + let searchParamRequest = {...formValue} + // dLine을 format에 맞는 문자열로 바꿔줌 + if(formValue.releaseDateFrom !== undefined){ + searchParamRequest.releaseDateFrom = formValue.releaseDateFrom.format().replace('+09:00','') + } + + if(formValue.releaseDateTo !== undefined){ + searchParamRequest.releaseDateTo = formValue.releaseDateTo.format().replace('+09:00','') + } + + props.containerRef.current.search(searchParamRequest) + }; + + return ( + + + + + + + + + + + +
+ + + ) +} + +export default ContainerTabControl \ No newline at end of file diff --git a/src/page/manager/palette/PaletteTab.js b/src/page/manager/palette/PaletteTab.js new file mode 100644 index 0000000..87c9266 --- /dev/null +++ b/src/page/manager/palette/PaletteTab.js @@ -0,0 +1,50 @@ +import {forwardRef, useEffect, useImperativeHandle, useState} from "react"; +import axios from "axios"; +import {Table} from "antd"; + +const PaletteTab = forwardRef((props, ref) => { + + const [pallete, setPallete] = useState([]); + + useEffect(()=>{ + getPalleteData() + },[]) + + useImperativeHandle(ref, () => ({ + async search(searchParam){ + let result = (await axios.get(`http://localhost:8080/palette`,{ + params: searchParam, + headers: {Authorization: `Bearer ${localStorage.getItem('accessToken')}`,}, + })).data + setPallete(result) + } + })); + const columns = [ + {title: '팔레트ID', dataIndex: 'paletteId', key: 'palleteId',}, + {title: '상품명', dataIndex: 'paletteName', key: 'paletteName',}, + {title: '수량(개)', dataIndex: 'quantity', key: 'quantity',}, + {title: '가로(m)', dataIndex: 'width', key: 'width',}, + {title: '세로(m)', dataIndex: 'length', key: 'length',}, + {title: '높이(m)', dataIndex: 'height', key: 'height',}, + {title: '부피(m^3)', dataIndex: 'volume', key: 'volume',}, + {title: '무게(kg)', dataIndex: 'weight', key: 'weight',}, + {title: '출고마감시간', dataIndex: 'deadLine', key: 'deadLine',}, + ]; + + const getPalleteData = async ()=>{ + let result = (await axios.get("http://localhost:8080/palette", + { + headers: {Authorization: `Bearer ${localStorage.getItem('accessToken')}`,}, + } + )).data + setPallete(result) + } + + return ( +
+
+ + ) +}) + +export default PaletteTab \ No newline at end of file diff --git a/src/page/manager/palette/PaletteTabControl.js b/src/page/manager/palette/PaletteTabControl.js new file mode 100644 index 0000000..6f9ffa6 --- /dev/null +++ b/src/page/manager/palette/PaletteTabControl.js @@ -0,0 +1,44 @@ +import {SearchOutlined} from '@ant-design/icons'; +import {Button, DatePicker, Form, Input, InputNumber} from "antd"; + + +const PaletteTabControl = (props) => { + const [searchParam] = Form.useForm() + + + const onSearch = async () => { + let formValue = await searchParam.validateFields() + let searchParamRequest = {...formValue} + // dLine을 format에 맞는 문자열로 바꿔줌 + if(formValue.dLineFrom !== undefined){ + searchParamRequest.dLineFrom = formValue.dLineFrom.format().replace('+09:00','') + } + + if(formValue.dLineTo !== undefined){ + searchParamRequest.dLineTo = formValue.dLineTo.format().replace('+09:00','') + } + + props.paletteRef.current.search(searchParamRequest) + }; + + return ( + + + + + + + + + + + + + + + + + ) +} + +export default PaletteTabControl \ No newline at end of file diff --git a/src/page/user/GoodsRegister.js b/src/page/user/GoodsRegister.js new file mode 100644 index 0000000..20d0c2a --- /dev/null +++ b/src/page/user/GoodsRegister.js @@ -0,0 +1,67 @@ +import {Button, DatePicker, Form, Input, InputNumber,} from 'antd'; +import axios from "axios"; + + +const GoodsRegister = (props) => { + const [newPallete] = Form.useForm() + + const registerPallete = async () => { + let createPaletteRequest + let canRegister = false + try { + // formValue를 유효성 검사한 후 통과하면 form의 데이터를 가져옴 + let formValue = await newPallete.validateFields() + createPaletteRequest = {...formValue} + // dLine을 format에 맞는 문자열로 바꿔줌 + createPaletteRequest.dLine = formValue.dLine.format().replace('+09:00', '') + canRegister = true + } catch (e) { + alert('필수값은 전부 입력해야합니다.') + } + if (!canRegister) return + try { + let result = (await axios.post("http://localhost:8080/palette", + createPaletteRequest, + { + headers: {Authorization: `Bearer ${localStorage.getItem('accessToken')}`,}, + } + )); + if (result.status === 200) + alert('등록되었습니다.') + } catch (e) { + console.log(e) + alert('등록 실패하였습니다.') + } + } + + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +}; + +export default GoodsRegister; \ No newline at end of file diff --git a/src/page/user/OrderDelivery.js b/src/page/user/OrderDelivery.js new file mode 100644 index 0000000..20be65d --- /dev/null +++ b/src/page/user/OrderDelivery.js @@ -0,0 +1,50 @@ +import {Anchor, Button, Layout, Table, Tabs} from "antd"; +import Sider from "antd/es/layout/Sider"; +import {Content} from "antd/es/layout/layout"; +import axios from "axios"; +import {forwardRef, useEffect, useImperativeHandle, useState} from "react"; +import Search from "antd/es/input/Search"; + +const contentStyle = { + textAlign: 'center', + minHeight: 120, + lineHeight: '120px', + backgroundColor: '#fff', +}; + +const OrderDelivery = forwardRef((props, ref) => { + const [orders, setOrders] = useState([]); + + useEffect(()=>{ + getOrderData() + },[]) + + + const columns = [ + {title: '번호', dataIndex: 'paletteId', key: 'paletteId',}, + {title: '상품명', dataIndex: 'paletteName', key: 'paletteName',}, + {title: '주문개수', dataIndex: 'quantity', key: 'quantity',}, + {title: '출고마감시간', dataIndex: 'deadLine', key: 'deadLine',}, + {title: '1차 배송지', dataIndex: 'firstDel', key: 'firstDel',}, + {title: '최종 배송지', dataIndex: 'finalDel', key: 'finalDel',}, + {title: '배송현황', dataIndex: 'delivery', key: 'delivery',}, + ]; + + + const getOrderData = async ()=>{ + let result = (await axios.get("http://localhost:8080/palette", + { + headers: {Authorization: `Bearer ${localStorage.getItem('accessToken')}`,},} + )).data + setOrders(result.map(value => ({...value, delivery:"배송중"}))) + } + + return ( + + +
+ + + ) +}) +export default OrderDelivery; \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 41ee892..e3f3bae 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2972,9 +2972,9 @@ axe-core@^4.6.2: integrity sha512-/BQzOX780JhsxDnPpH4ZiyrJAzcd8AfzFPkv+89veFSr1rcMjuq2JDCwypKaPeB6ljHp9KjXhPpjgCvQlWYuqg== axios@^1.3.5: - version "1.3.5" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.3.5.tgz#e07209b39a0d11848e3e341fa087acd71dadc542" - integrity sha512-glL/PvG/E+xCWwV8S6nCHcrfg1exGx7vxyUIivIA1iL7BIh6bePylCfVHwp6k13ao7SATxB6imau2kqY+I67kw== + version "1.4.0" + resolved "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz" + integrity sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA== dependencies: follow-redirects "^1.15.0" form-data "^4.0.0" @@ -4931,7 +4931,7 @@ form-data@^3.0.0: form-data@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" + resolved "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz" integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== dependencies: asynckit "^0.4.0" @@ -7835,7 +7835,7 @@ proxy-addr@~2.0.7: proxy-from-env@^1.1.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + resolved "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz" integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== psl@^1.1.33: @@ -8307,6 +8307,11 @@ react-bootstrap@^2.7.2: uncontrollable "^7.2.1" warning "^4.0.3" +react-daum-postcode@^3.1.1: + version "3.1.1" + resolved "https://registry.npmjs.org/react-daum-postcode/-/react-daum-postcode-3.1.1.tgz" + integrity sha512-IFlC8XBSK+uobSIBHaWlxeecYpv9RhCFNu4YJ3+CrfGyEVdc4+yaaUH6BIfJbTZOybVx0V3s4nUeAEsssXBNJg== + react-dev-utils@^12.0.1: version "12.0.1" resolved "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz" @@ -8406,7 +8411,7 @@ react-router-dom@^6.10.0: "@remix-run/router" "1.5.0" react-router "6.10.0" -react-router@6.10.0, react-router@^6.10.0: +react-router@^6.10.0, react-router@6.10.0: version "6.10.0" resolved "https://registry.npmjs.org/react-router/-/react-router-6.10.0.tgz" integrity sha512-Nrg0BWpQqrC3ZFFkyewrflCud9dio9ME3ojHCF/WLsprJVzkq3q3UeEhMCAW1dobjeGbWgjNn/PVF6m46ANxXQ== @@ -9467,6 +9472,11 @@ text-table@^0.2.0: resolved "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz" integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== +three@^0.152.2: + version "0.152.2" + resolved "https://registry.npmjs.org/three/-/three-0.152.2.tgz" + integrity sha512-Ff9zIpSfkkqcBcpdiFo2f35vA9ZucO+N8TNacJOqaEE6DrB0eufItVMib8bK8Pcju/ZNT6a7blE1GhTpkdsILw== + throat@^6.0.1: version "6.0.2" resolved "https://registry.npmjs.org/throat/-/throat-6.0.2.tgz"