diff --git a/package-lock.json b/package-lock.json
index 01203b4..6478421 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -22,6 +22,9 @@
"socket.io": "^4.8.0",
"socket.io-client": "^4.8.0",
"web-vitals": "^2.1.4"
+ },
+ "devDependencies": {
+ "sass": "^1.79.3"
}
},
"node_modules/@adobe/css-tools": {
@@ -10356,6 +10359,13 @@
"url": "https://opencollective.com/immer"
}
},
+ "node_modules/immutable": {
+ "version": "4.3.7",
+ "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.7.tgz",
+ "integrity": "sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==",
+ "devOptional": true,
+ "license": "MIT"
+ },
"node_modules/import-fresh": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
@@ -17053,6 +17063,24 @@
"integrity": "sha512-ZRwKbh/eQ6w9vmTjkuG0Ioi3HBwPFce0O+v//ve+aOq1oeCy7jMV2qzzAlpsNuqpqCBjjriM1lbtZbF/Q8jVyA==",
"license": "CC0-1.0"
},
+ "node_modules/sass": {
+ "version": "1.79.3",
+ "resolved": "https://registry.npmjs.org/sass/-/sass-1.79.3.tgz",
+ "integrity": "sha512-m7dZxh0W9EZ3cw50Me5GOuYm/tVAJAn91SUnohLRo9cXBixGUOdvmryN+dXpwR831bhoY3Zv7rEFt85PUwTmzA==",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "chokidar": "^4.0.0",
+ "immutable": "^4.0.0",
+ "source-map-js": ">=0.6.2 <2.0.0"
+ },
+ "bin": {
+ "sass": "sass.js"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
"node_modules/sass-loader": {
"version": "12.6.0",
"resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-12.6.0.tgz",
@@ -17091,6 +17119,36 @@
}
}
},
+ "node_modules/sass/node_modules/chokidar": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz",
+ "integrity": "sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "readdirp": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 14.16.0"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/sass/node_modules/readdirp": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.1.tgz",
+ "integrity": "sha512-GkMg9uOTpIWWKbSsgwb5fA4EavTR+SG/PMPoAY8hkhHfEEY0/vqljY+XHqtDf2cr2IJtoNRDbrrEpZUiZCkYRw==",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 14.16.0"
+ },
+ "funding": {
+ "type": "individual",
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
"node_modules/sax": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
diff --git a/package.json b/package.json
index 4350e13..fb34334 100644
--- a/package.json
+++ b/package.json
@@ -41,5 +41,8 @@
"last 1 firefox version",
"last 1 safari version"
]
+ },
+ "devDependencies": {
+ "sass": "^1.79.3"
}
}
diff --git a/src/App.js b/src/App.js
index 804bd00..d705d14 100644
--- a/src/App.js
+++ b/src/App.js
@@ -3,6 +3,7 @@ import DeviceGroups from "./pages/DeviceGroups";
import Devices from "./pages/Devices";
import Sidebar from "./Sidebar";
import Dashboard from './pages/Dashboard';
+import UserAccount from './pages/UserAccount'; // Импортируем страницу аккаунта
const App = () => {
const [activeTab, setActiveTab] = useState('map'); // По умолчанию активная вкладка "Карта"
@@ -13,7 +14,7 @@ const App = () => {
{activeTab === 'map' &&
} {/* Подключаем компонент Dashboard */}
{activeTab === 'connection' &&
Подключение
}
- {activeTab === 'account' &&
Аккаунт пользователя
}
+ {activeTab === 'account' &&
} {/* Подключаем компонент аккаунта */}
{activeTab === 'groups' &&
} {/* Группы устройств */}
{activeTab === 'devices' &&
} {/* Устройства */}
diff --git a/src/Sidebar.js b/src/Sidebar.js
index 1a288f0..c27cbba 100644
--- a/src/Sidebar.js
+++ b/src/Sidebar.js
@@ -1,7 +1,13 @@
-import React from 'react';
+import React, { useState } from 'react';
import './Sidebar.css';
const Sidebar = ({ onSelectTab, activeTab }) => {
+ const [isDropdownOpen, setIsDropdownOpen] = useState(false);
+
+ const toggleDropdown = () => {
+ setIsDropdownOpen(!isDropdownOpen); // Переключаем состояние выпадающего списка
+ };
+
return (
Меню
@@ -12,15 +18,26 @@ const Sidebar = ({ onSelectTab, activeTab }) => {
onSelectTab('connection')}>
Подключение
- onSelectTab('account')}>
+ {
+ onSelectTab('account');
+ toggleDropdown();
+ }}
+ >
Аккаунт пользователя
- onSelectTab('groups')}>
- Группы устройств
-
- onSelectTab('devices')}>
- Устройства
-
+ {/* Выпадающий список для групп и устройств */}
+ {isDropdownOpen && (
+ <>
+ onSelectTab('groups')}>
+ Группы устройств
+
+ onSelectTab('devices')}>
+ Устройства
+
+ >
+ )}
);
diff --git a/src/UserAccount.scss b/src/UserAccount.scss
new file mode 100644
index 0000000..eb5cf87
--- /dev/null
+++ b/src/UserAccount.scss
@@ -0,0 +1,87 @@
+.user-account {
+ padding: 20px;
+ background-color: #f4f4f4;
+ border-radius: 10px;
+ max-width: 400px;
+ margin: 0 auto;
+
+ h1 {
+ text-align: center;
+ margin-bottom: 20px;
+ }
+
+ .user-info, .edit-form {
+ display: flex;
+ flex-direction: column;
+ gap: 10px;
+
+ label {
+ display: flex;
+ justify-content: space-between;
+ font-size: 16px;
+ }
+
+ input {
+ padding: 8px;
+ font-size: 14px;
+ border: 1px solid #ccc;
+ border-radius: 5px;
+ }
+
+ p {
+ font-size: 18px;
+ margin: 10px 0;
+ }
+
+ .buttons {
+ display: flex;
+ justify-content: space-between;
+
+ button {
+ padding: 10px 20px;
+ font-size: 14px;
+ cursor: pointer;
+ border: none;
+ border-radius: 5px;
+ background-color: #3498db;
+ color: white;
+ transition: background-color 0.3s ease;
+
+ &:hover {
+ background-color: #2980b9;
+ }
+
+ &:last-child {
+ background-color: #e74c3c;
+
+ &:hover {
+ background-color: #c0392b;
+ }
+ }
+ }
+ }
+ }
+
+ .edit-button {
+ margin-top: 20px;
+ padding: 10px 25px;
+ font-size: 16px;
+ font-weight: bold;
+ cursor: pointer;
+ background-color: #2ecc71; /* Зелёный цвет */
+ color: white;
+ border: none;
+ border-radius: 5px;
+ transition: background-color 0.3s ease, transform 0.2s ease;
+
+ &:hover {
+ background-color: #27ae60;
+ transform: scale(1.05); /* Небольшой зум при наведении */
+ }
+
+ &:active {
+ background-color: #1e8449;
+ transform: scale(0.98); /* Легкий уменьшенный эффект при нажатии */
+ }
+ }
+ }
\ No newline at end of file
diff --git a/src/pages/Login.js b/src/pages/Login.js
new file mode 100644
index 0000000..0fb96cb
--- /dev/null
+++ b/src/pages/Login.js
@@ -0,0 +1,42 @@
+import React, { useState } from 'react';
+import './Login.css';
+
+const Login = ({ onLogin }) => {
+ const [username, setUsername] = useState('');
+ const [password, setPassword] = useState('');
+ const [error, setError] = useState('');
+
+ const handleSubmit = (e) => {
+ e.preventDefault();
+ // Простейшая проверка логина/пароля
+ if (username === 'admin' && password === 'admin') {
+ onLogin(); // Вызываем функцию при успешной авторизации
+ } else {
+ setError('Неверный логин или пароль');
+ }
+ };
+
+ return (
+
+ );
+};
+
+export default Login;
\ No newline at end of file
diff --git a/src/pages/UserAccount.js b/src/pages/UserAccount.js
new file mode 100644
index 0000000..0440cc8
--- /dev/null
+++ b/src/pages/UserAccount.js
@@ -0,0 +1,84 @@
+import React, { useState } from 'react';
+import '../UserAccount.scss';
+
+const UserAccount = () => {
+ const [userData, setUserData] = useState({
+ username: 'Мамут Рахал',
+ email: 'yatupoidayn@mail.ru',
+ phone: '+666',
+ });
+
+ const [isEditing, setIsEditing] = useState(false);
+ const [formData, setFormData] = useState(userData);
+
+ const handleChange = (e) => {
+ const { name, value } = e.target;
+ setFormData((prevData) => ({
+ ...prevData,
+ [name]: value,
+ }));
+ };
+
+ const handleSave = () => {
+ setUserData(formData);
+ setIsEditing(false);
+ };
+
+ const handleCancel = () => {
+ setFormData(userData);
+ setIsEditing(false);
+ };
+
+ return (
+
+
Данные
+
+ {isEditing ? (
+
+ ) : (
+
+
Имя: {userData.username}
+
Email: {userData.email}
+
Телефон: {userData.phone}
+
+
+ )}
+
+ );
+};
+
+export default UserAccount;
\ No newline at end of file