Merge pull request 'big_glist' (#5) from big_glist into main
Reviewed-on: https://maktraher.ru/enemy01/jopa/pulls/5
This commit is contained in:
commit
70115fc8bb
144
package-lock.json
generated
144
package-lock.json
generated
@ -11,11 +11,15 @@
|
|||||||
"@testing-library/jest-dom": "^5.17.0",
|
"@testing-library/jest-dom": "^5.17.0",
|
||||||
"@testing-library/react": "^13.4.0",
|
"@testing-library/react": "^13.4.0",
|
||||||
"@testing-library/user-event": "^13.5.0",
|
"@testing-library/user-event": "^13.5.0",
|
||||||
|
"axios": "^1.7.7",
|
||||||
|
"express": "^4.21.0",
|
||||||
|
"jsonwebtoken": "^9.0.2",
|
||||||
"leaflet": "^1.9.4",
|
"leaflet": "^1.9.4",
|
||||||
"leaflet-defaulticon-compatibility": "^0.1.2",
|
"leaflet-defaulticon-compatibility": "^0.1.2",
|
||||||
"qrcode.react": "^4.0.1",
|
"qrcode.react": "^4.0.1",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
|
"react-image-crop": "^11.0.7",
|
||||||
"react-leaflet": "^4.2.1",
|
"react-leaflet": "^4.2.1",
|
||||||
"react-router-dom": "^6.26.2",
|
"react-router-dom": "^6.26.2",
|
||||||
"react-scripts": "5.0.1",
|
"react-scripts": "5.0.1",
|
||||||
@ -5862,6 +5866,31 @@
|
|||||||
"node": ">=4"
|
"node": ">=4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/axios": {
|
||||||
|
"version": "1.7.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz",
|
||||||
|
"integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"follow-redirects": "^1.15.6",
|
||||||
|
"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==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"asynckit": "^0.4.0",
|
||||||
|
"combined-stream": "^1.0.8",
|
||||||
|
"mime-types": "^2.1.12"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/axobject-query": {
|
"node_modules/axobject-query": {
|
||||||
"version": "4.1.0",
|
"version": "4.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz",
|
||||||
@ -6384,6 +6413,12 @@
|
|||||||
"node-int64": "^0.4.0"
|
"node-int64": "^0.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/buffer-equal-constant-time": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==",
|
||||||
|
"license": "BSD-3-Clause"
|
||||||
|
},
|
||||||
"node_modules/buffer-from": {
|
"node_modules/buffer-from": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
|
||||||
@ -7792,6 +7827,15 @@
|
|||||||
"integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
|
"integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/ecdsa-sig-formatter": {
|
||||||
|
"version": "1.0.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
|
||||||
|
"integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"safe-buffer": "^5.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/ee-first": {
|
"node_modules/ee-first": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
|
||||||
@ -13417,6 +13461,28 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/jsonwebtoken": {
|
||||||
|
"version": "9.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz",
|
||||||
|
"integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"jws": "^3.2.2",
|
||||||
|
"lodash.includes": "^4.3.0",
|
||||||
|
"lodash.isboolean": "^3.0.3",
|
||||||
|
"lodash.isinteger": "^4.0.4",
|
||||||
|
"lodash.isnumber": "^3.0.3",
|
||||||
|
"lodash.isplainobject": "^4.0.6",
|
||||||
|
"lodash.isstring": "^4.0.1",
|
||||||
|
"lodash.once": "^4.0.0",
|
||||||
|
"ms": "^2.1.1",
|
||||||
|
"semver": "^7.5.4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12",
|
||||||
|
"npm": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/jsx-ast-utils": {
|
"node_modules/jsx-ast-utils": {
|
||||||
"version": "3.3.5",
|
"version": "3.3.5",
|
||||||
"resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz",
|
"resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz",
|
||||||
@ -13432,6 +13498,27 @@
|
|||||||
"node": ">=4.0"
|
"node": ">=4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/jwa": {
|
||||||
|
"version": "1.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz",
|
||||||
|
"integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"buffer-equal-constant-time": "1.0.1",
|
||||||
|
"ecdsa-sig-formatter": "1.0.11",
|
||||||
|
"safe-buffer": "^5.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/jws": {
|
||||||
|
"version": "3.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz",
|
||||||
|
"integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"jwa": "^1.4.1",
|
||||||
|
"safe-buffer": "^5.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/keyv": {
|
"node_modules/keyv": {
|
||||||
"version": "4.5.4",
|
"version": "4.5.4",
|
||||||
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
|
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
|
||||||
@ -13592,6 +13679,42 @@
|
|||||||
"integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==",
|
"integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/lodash.includes": {
|
||||||
|
"version": "4.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
|
||||||
|
"integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/lodash.isboolean": {
|
||||||
|
"version": "3.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
|
||||||
|
"integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/lodash.isinteger": {
|
||||||
|
"version": "4.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
|
||||||
|
"integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/lodash.isnumber": {
|
||||||
|
"version": "3.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
|
||||||
|
"integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/lodash.isplainobject": {
|
||||||
|
"version": "4.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
|
||||||
|
"integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/lodash.isstring": {
|
||||||
|
"version": "4.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
|
||||||
|
"integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/lodash.memoize": {
|
"node_modules/lodash.memoize": {
|
||||||
"version": "4.1.2",
|
"version": "4.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
|
||||||
@ -13604,6 +13727,12 @@
|
|||||||
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
|
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/lodash.once": {
|
||||||
|
"version": "4.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
|
||||||
|
"integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/lodash.sortby": {
|
"node_modules/lodash.sortby": {
|
||||||
"version": "4.7.0",
|
"version": "4.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz",
|
||||||
@ -16015,6 +16144,12 @@
|
|||||||
"node": ">= 0.10"
|
"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==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/psl": {
|
"node_modules/psl": {
|
||||||
"version": "1.9.0",
|
"version": "1.9.0",
|
||||||
"resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz",
|
"resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz",
|
||||||
@ -16395,6 +16530,15 @@
|
|||||||
"integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==",
|
"integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/react-image-crop": {
|
||||||
|
"version": "11.0.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-image-crop/-/react-image-crop-11.0.7.tgz",
|
||||||
|
"integrity": "sha512-ZciKWHDYzmm366JDL18CbrVyjnjH0ojufGDmScfS4ZUqLHg4nm6ATY+K62C75W4ZRNt4Ii+tX0bSjNk9LQ2xzQ==",
|
||||||
|
"license": "ISC",
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": ">=16.13.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-is": {
|
"node_modules/react-is": {
|
||||||
"version": "17.0.2",
|
"version": "17.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
|
||||||
|
@ -6,11 +6,15 @@
|
|||||||
"@testing-library/jest-dom": "^5.17.0",
|
"@testing-library/jest-dom": "^5.17.0",
|
||||||
"@testing-library/react": "^13.4.0",
|
"@testing-library/react": "^13.4.0",
|
||||||
"@testing-library/user-event": "^13.5.0",
|
"@testing-library/user-event": "^13.5.0",
|
||||||
|
"axios": "^1.7.7",
|
||||||
|
"express": "^4.21.0",
|
||||||
|
"jsonwebtoken": "^9.0.2",
|
||||||
"leaflet": "^1.9.4",
|
"leaflet": "^1.9.4",
|
||||||
"leaflet-defaulticon-compatibility": "^0.1.2",
|
"leaflet-defaulticon-compatibility": "^0.1.2",
|
||||||
"qrcode.react": "^4.0.1",
|
"qrcode.react": "^4.0.1",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
|
"react-image-crop": "^11.0.7",
|
||||||
"react-leaflet": "^4.2.1",
|
"react-leaflet": "^4.2.1",
|
||||||
"react-router-dom": "^6.26.2",
|
"react-router-dom": "^6.26.2",
|
||||||
"react-scripts": "5.0.1",
|
"react-scripts": "5.0.1",
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
work correctly both with client-side routing and a non-root public URL.
|
work correctly both with client-side routing and a non-root public URL.
|
||||||
Learn how to configure a non-root public URL by running `npm run build`.
|
Learn how to configure a non-root public URL by running `npm run build`.
|
||||||
-->
|
-->
|
||||||
<title>React App</title>
|
<title>YANDEX ZAKLADKI</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 15 KiB |
Binary file not shown.
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 15 KiB |
@ -1,87 +1,140 @@
|
|||||||
.user-account {
|
.user-account {
|
||||||
padding: 20px;
|
padding: 40px;
|
||||||
background-color: #f4f4f4;
|
background-color: #ffffff;
|
||||||
border-radius: 10px;
|
border-radius: 15px;
|
||||||
max-width: 400px;
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
||||||
margin: 0 auto;
|
max-width: 600px;
|
||||||
|
margin: 60px auto;
|
||||||
h1 {
|
font-family: 'Arial', sans-serif;
|
||||||
text-align: center;
|
|
||||||
|
h1 {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 28px;
|
||||||
|
color: #333;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-info, .edit-form {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 20px;
|
||||||
|
|
||||||
|
.avatar-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-start;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
border-radius: 50%;
|
||||||
|
object-fit: cover;
|
||||||
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar-placeholder {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
background-color: #3498db;
|
||||||
|
color: white;
|
||||||
|
font-size: 36px;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.user-info, .edit-form {
|
p, input {
|
||||||
|
font-size: 18px;
|
||||||
|
color: #333;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
padding: 10px 15px;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
border-radius: 8px;
|
||||||
|
background-color: #f9f9f9;
|
||||||
|
outline: none;
|
||||||
|
transition: border-color 0.3s ease;
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
border-color: #3498db;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 10px;
|
font-size: 16px;
|
||||||
|
color: #666;
|
||||||
label {
|
margin-bottom: 15px;
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
input[type="text"], input[type="email"], input[type="tel"], input[type="file"] {
|
||||||
|
padding: 10px;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
|
border-radius: 8px;
|
||||||
|
background-color: #f9f9f9;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
margin-top: 10px;
|
||||||
|
transition: border-color 0.3s ease;
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
border-color: #3498db;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
input {
|
|
||||||
padding: 8px;
|
.buttons {
|
||||||
font-size: 14px;
|
display: flex;
|
||||||
border: 1px solid #ccc;
|
justify-content: space-between;
|
||||||
border-radius: 5px;
|
|
||||||
}
|
button {
|
||||||
|
padding: 14px 30px;
|
||||||
p {
|
font-size: 16px;
|
||||||
font-size: 18px;
|
cursor: pointer;
|
||||||
margin: 10px 0;
|
border: none;
|
||||||
}
|
border-radius: 8px;
|
||||||
|
background-color: #3498db;
|
||||||
.buttons {
|
color: white;
|
||||||
display: flex;
|
transition: background-color 0.3s ease, transform 0.2s ease;
|
||||||
justify-content: space-between;
|
|
||||||
|
&:hover {
|
||||||
button {
|
background-color: #2980b9;
|
||||||
padding: 10px 20px;
|
transform: scale(1.03);
|
||||||
font-size: 14px;
|
}
|
||||||
cursor: pointer;
|
|
||||||
border: none;
|
&:last-child {
|
||||||
border-radius: 5px;
|
background-color: #e74c3c;
|
||||||
background-color: #3498db;
|
|
||||||
color: white;
|
|
||||||
transition: background-color 0.3s ease;
|
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: #2980b9;
|
background-color: #c0392b;
|
||||||
}
|
|
||||||
|
|
||||||
&:last-child {
|
|
||||||
background-color: #e74c3c;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: #c0392b;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
.edit-button {
|
|
||||||
margin-top: 20px;
|
.edit-button {
|
||||||
padding: 10px 25px;
|
margin-top: 30px;
|
||||||
font-size: 16px;
|
padding: 14px 35px;
|
||||||
font-weight: bold;
|
font-size: 18px;
|
||||||
cursor: pointer;
|
font-weight: 600;
|
||||||
background-color: #2ecc71; /* Зелёный цвет */
|
cursor: pointer;
|
||||||
color: white;
|
background-color: #2ecc71;
|
||||||
border: none;
|
color: white;
|
||||||
border-radius: 5px;
|
border: none;
|
||||||
transition: background-color 0.3s ease, transform 0.2s ease;
|
border-radius: 8px;
|
||||||
|
transition: background-color 0.3s ease, transform 0.3s ease;
|
||||||
&:hover {
|
|
||||||
background-color: #27ae60;
|
&:hover {
|
||||||
transform: scale(1.05); /* Небольшой зум при наведении */
|
background-color: #27ae60;
|
||||||
}
|
transform: scale(1.05);
|
||||||
|
|
||||||
&:active {
|
|
||||||
background-color: #1e8449;
|
|
||||||
transform: scale(0.98); /* Легкий уменьшенный эффект при нажатии */
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
&:active {
|
||||||
|
background-color: #1e8449;
|
||||||
|
transform: scale(0.98);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { QRCodeCanvas } from "qrcode.react";
|
import { QRCodeCanvas } from "qrcode.react";
|
||||||
|
import axios from 'axios';
|
||||||
import '../Devices.css';
|
import '../Devices.css';
|
||||||
|
|
||||||
const Devices = () => {
|
const Devices = () => {
|
||||||
@ -7,10 +8,26 @@ const Devices = () => {
|
|||||||
const [selectedDevice, setSelectedDevice] = useState(null);
|
const [selectedDevice, setSelectedDevice] = useState(null);
|
||||||
const [deviceName, setDeviceName] = useState('');
|
const [deviceName, setDeviceName] = useState('');
|
||||||
const [deviceStatus, setDeviceStatus] = useState('');
|
const [deviceStatus, setDeviceStatus] = useState('');
|
||||||
|
const [isRegenerating, setIsRegenerating] = useState(false); // отображение генерации токена
|
||||||
|
const [showFullToken, setShowFullToken] = useState({}); // управление отображением токена
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// получение устройств
|
||||||
|
const fetchDevices = async () => {
|
||||||
|
try {
|
||||||
|
const response = await axios.get('/api/devices'); // потом нужно будет заменить на нашу апишку
|
||||||
|
setDevices(response.data.devices);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Ошибка при загрузке устройств:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
fetchDevices();
|
||||||
|
}, []);
|
||||||
|
|
||||||
const addDevice = () => {
|
const addDevice = () => {
|
||||||
if (deviceName) {
|
if (deviceName) {
|
||||||
const newDevice = { name: deviceName, status: deviceStatus || 'Неактивен', id: Date.now() };
|
const newDevice = { name: deviceName, status: deviceStatus || 'Неактивен', id: Date.now(), access_key: '' };
|
||||||
setDevices([...devices, newDevice]);
|
setDevices([...devices, newDevice]);
|
||||||
setDeviceName('');
|
setDeviceName('');
|
||||||
setDeviceStatus('');
|
setDeviceStatus('');
|
||||||
@ -38,6 +55,25 @@ const Devices = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// генерация токена
|
||||||
|
const handleShowFullToken = (deviceId) => {
|
||||||
|
setShowFullToken(prevState => ({ ...prevState, [deviceId]: !prevState[deviceId] }));
|
||||||
|
};
|
||||||
|
|
||||||
|
// пересоздание токена
|
||||||
|
const handleRegenerateToken = async (deviceId) => {
|
||||||
|
setIsRegenerating(true);
|
||||||
|
try {
|
||||||
|
const response = await axios.post(`/api/devices/${deviceId}/regenerate-token`); // тоже заменить на апишку
|
||||||
|
setDevices(devices.map(device =>
|
||||||
|
device.id === deviceId ? { ...device, access_key: response.data.access_key } : device
|
||||||
|
));
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Ошибка при пересоздании токена:', error);
|
||||||
|
}
|
||||||
|
setIsRegenerating(false);
|
||||||
|
};
|
||||||
|
|
||||||
const generateQR = (device) => {
|
const generateQR = (device) => {
|
||||||
return (
|
return (
|
||||||
<QRCodeCanvas value={JSON.stringify(device)} size={128} />
|
<QRCodeCanvas value={JSON.stringify(device)} size={128} />
|
||||||
@ -65,6 +101,7 @@ const Devices = () => {
|
|||||||
<th>Название</th>
|
<th>Название</th>
|
||||||
<th>Статус</th>
|
<th>Статус</th>
|
||||||
<th>QR Код</th>
|
<th>QR Код</th>
|
||||||
|
<th>Токен устройства</th>
|
||||||
<th>Действия</th>
|
<th>Действия</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
@ -74,8 +111,24 @@ const Devices = () => {
|
|||||||
<td>{device.name}</td>
|
<td>{device.name}</td>
|
||||||
<td>{device.status}</td>
|
<td>{device.status}</td>
|
||||||
<td>{generateQR(device)}</td>
|
<td>{generateQR(device)}</td>
|
||||||
|
<td>
|
||||||
|
{showFullToken[device.id] ? (
|
||||||
|
device.access_key
|
||||||
|
) : (
|
||||||
|
<span>{device.access_key.slice(0, 6)}...</span>
|
||||||
|
)}
|
||||||
|
<button onClick={() => handleShowFullToken(device.id)}>
|
||||||
|
{showFullToken[device.id] ? 'Скрыть' : 'Показать'}
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<button onClick={editDevice}>Редактировать</button>
|
<button onClick={editDevice}>Редактировать</button>
|
||||||
|
<button
|
||||||
|
onClick={() => handleRegenerateToken(device.id)}
|
||||||
|
disabled={isRegenerating}
|
||||||
|
>
|
||||||
|
{isRegenerating ? 'Пересоздание...' : 'Пересоздать токен'}
|
||||||
|
</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
))}
|
))}
|
||||||
|
@ -6,6 +6,7 @@ const UserAccount = () => {
|
|||||||
username: 'Мамут Рахал',
|
username: 'Мамут Рахал',
|
||||||
email: 'yatupoidayn@mail.ru',
|
email: 'yatupoidayn@mail.ru',
|
||||||
phone: '+666',
|
phone: '+666',
|
||||||
|
avatar: '', // Новое поле для аватара
|
||||||
});
|
});
|
||||||
|
|
||||||
const [isEditing, setIsEditing] = useState(false);
|
const [isEditing, setIsEditing] = useState(false);
|
||||||
@ -19,6 +20,21 @@ const UserAccount = () => {
|
|||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Функция для загрузки аватара
|
||||||
|
const handleAvatarChange = (e) => {
|
||||||
|
const file = e.target.files[0];
|
||||||
|
if (file) {
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.onloadend = () => {
|
||||||
|
setFormData((prevData) => ({
|
||||||
|
...prevData,
|
||||||
|
avatar: reader.result,
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
reader.readAsDataURL(file);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const handleSave = () => {
|
const handleSave = () => {
|
||||||
setUserData(formData);
|
setUserData(formData);
|
||||||
setIsEditing(false);
|
setIsEditing(false);
|
||||||
@ -62,6 +78,14 @@ const UserAccount = () => {
|
|||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
|
<label>
|
||||||
|
Загрузить аватар:
|
||||||
|
<input
|
||||||
|
type="file"
|
||||||
|
accept="image/*"
|
||||||
|
onChange={handleAvatarChange}
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
<div className="buttons">
|
<div className="buttons">
|
||||||
<button onClick={handleSave}>Сохранить</button>
|
<button onClick={handleSave}>Сохранить</button>
|
||||||
<button onClick={handleCancel}>Отмена</button>
|
<button onClick={handleCancel}>Отмена</button>
|
||||||
@ -69,6 +93,13 @@ const UserAccount = () => {
|
|||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="user-info">
|
<div className="user-info">
|
||||||
|
<div className="avatar-container">
|
||||||
|
{userData.avatar ? (
|
||||||
|
<img src={userData.avatar} alt="User Avatar" className="avatar" />
|
||||||
|
) : (
|
||||||
|
<div className="avatar-placeholder">A</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
<p><strong>Имя:</strong> {userData.username}</p>
|
<p><strong>Имя:</strong> {userData.username}</p>
|
||||||
<p><strong>Email:</strong> {userData.email}</p>
|
<p><strong>Email:</strong> {userData.email}</p>
|
||||||
<p><strong>Телефон:</strong> {userData.phone}</p>
|
<p><strong>Телефон:</strong> {userData.phone}</p>
|
||||||
|
Loading…
Reference in New Issue
Block a user