diff --git a/src/App.js b/src/App.js index d705d14..40ed20d 100644 --- a/src/App.js +++ b/src/App.js @@ -3,20 +3,37 @@ import DeviceGroups from "./pages/DeviceGroups"; import Devices from "./pages/Devices"; import Sidebar from "./Sidebar"; import Dashboard from './pages/Dashboard'; -import UserAccount from './pages/UserAccount'; // Импортируем страницу аккаунта +import UserAccount from './pages/UserAccount'; // Импортируем компонент UserAccount +import Login from './pages/Login'; // Импортируем страницу логина +import Connections from './pages/Connections'; // Импортируем страницу подключений const App = () => { const [activeTab, setActiveTab] = useState('map'); // По умолчанию активная вкладка "Карта" + const [isAuthenticated, setIsAuthenticated] = useState(false); // Статус авторизации + + const handleLogin = () => { + setIsAuthenticated(true); // Устанавливаем авторизацию + }; + + const handleLogout = () => { + setIsAuthenticated(false); // Сбрасываем авторизацию + }; + + if (!isAuthenticated) { + return ; // Показываем страницу логина + } return ( -
- {/* Передаем активную вкладку */} -
- {activeTab === 'map' && } {/* Подключаем компонент Dashboard */} - {activeTab === 'connection' &&
Подключение
} - {activeTab === 'account' && } {/* Подключаем компонент аккаунта */} - {activeTab === 'groups' && } {/* Группы устройств */} - {activeTab === 'devices' && } {/* Устройства */} +
+
+ {/* Передаем onLogout */} +
+ {activeTab === 'map' && } {/* Подключаем компонент Dashboard */} + {activeTab === 'connection' && } {/* Страница подключений */} + {activeTab === 'account' && } {/* Подключаем компонент UserAccount */} + {activeTab === 'groups' && } {/* Группы устройств */} + {activeTab === 'devices' && } {/* Устройства */} +
); diff --git a/src/Connections.scss b/src/Connections.scss new file mode 100644 index 0000000..f95be0f --- /dev/null +++ b/src/Connections.scss @@ -0,0 +1,34 @@ +.section { + margin-bottom: 20px; + + form { + input { + margin-right: 10px; + padding: 8px; + border-radius: 4px; + border: 1px solid #ddd; + } + + button { + padding: 8px 12px; + background-color: #2980b9; + color: white; + border: none; + border-radius: 4px; + cursor: pointer; + + &:hover { + background-color: #3498db; + } + } + } + + ul { + list-style-type: none; + padding: 0; + + li { + margin-top: 10px; + } + } + } \ No newline at end of file diff --git a/src/Login.scss b/src/Login.scss new file mode 100644 index 0000000..3daef89 --- /dev/null +++ b/src/Login.scss @@ -0,0 +1,70 @@ +// styles/Login.scss + +.login-container { + display: flex; + justify-content: center; + align-items: center; + height: 100vh; + background-color: #f0f0f0; + + .login-box { + background-color: #fff; + padding: 40px; + border-radius: 8px; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); + max-width: 400px; + width: 100%; + display: flex; + flex-direction: column; // Выровнять элементы по колонке + + h2 { + text-align: center; + margin-bottom: 20px; + color: #333; + } + + form { + display: flex; + flex-direction: column; + + .input-group { + display: flex; + flex-direction: column; + margin-bottom: 20px; + + label { + margin-bottom: 8px; + color: #666; + font-size: 14px; + } + + input { + padding: 10px; + border: 1px solid #ddd; + border-radius: 4px; + font-size: 16px; + transition: border-color 0.3s ease; + &:focus { + outline: none; + border-color: #007bff; + } + } + } + + button { + padding: 12px; + background-color: #007bff; + color: #fff; + border: none; + border-radius: 4px; + font-size: 16px; + cursor: pointer; + transition: background-color 0.3s ease; + + &:hover { + background-color: #0056b3; + } + } + } + } + } \ No newline at end of file diff --git a/src/Sidebar.js b/src/Sidebar.js index c27cbba..e5304f2 100644 --- a/src/Sidebar.js +++ b/src/Sidebar.js @@ -1,11 +1,12 @@ -import React, { useState } from 'react'; -import './Sidebar.css'; +import React, { useState } from 'react'; // Ensure useState is imported +import './Sidebar.css'; // Change this to Sidebar.scss if using SCSS -const Sidebar = ({ onSelectTab, activeTab }) => { - const [isDropdownOpen, setIsDropdownOpen] = useState(false); +const Sidebar = ({ onSelectTab, activeTab, onLogout }) => { + const [isSubMenuOpen, setIsSubMenuOpen] = useState(false); // For managing dropdown items - const toggleDropdown = () => { - setIsDropdownOpen(!isDropdownOpen); // Переключаем состояние выпадающего списка + const toggleSubMenu = () => { + setIsSubMenuOpen(!isSubMenuOpen); + onSelectTab('account'); // Keep the logic to display the account when clicking on "Аккаунт пользователя" }; return ( @@ -18,17 +19,10 @@ const Sidebar = ({ onSelectTab, activeTab }) => {
  • onSelectTab('connection')}> Подключение
  • -
  • { - onSelectTab('account'); - toggleDropdown(); - }} - > +
  • Аккаунт пользователя
  • - {/* Выпадающий список для групп и устройств */} - {isDropdownOpen && ( + {isSubMenuOpen && ( // Dropdown menu <>
  • onSelectTab('groups')}> Группы устройств @@ -38,6 +32,9 @@ const Sidebar = ({ onSelectTab, activeTab }) => {
  • )} +
  • + Выйти +
  • ); diff --git a/src/pages/Connections.js b/src/pages/Connections.js new file mode 100644 index 0000000..edc243b --- /dev/null +++ b/src/pages/Connections.js @@ -0,0 +1,63 @@ +import React, { useState } from 'react'; +import '../Connections.scss'; + +const Connections = () => { + const [webhooks, setWebhooks] = useState([]); + const [websocketUrl, setWebsocketUrl] = useState(''); + + const addWebhook = (newWebhook) => { + setWebhooks([...webhooks, newWebhook]); + }; + + const handleWebhookSubmit = (e) => { + e.preventDefault(); + const newWebhook = { + url: e.target.webhookUrl.value, + groups: e.target.groups.value.split(','), + }; + addWebhook(newWebhook); + e.target.reset(); + }; + + return ( +
    +

    Подключения

    + + {/* Webhook подключение */} +
    +

    Подключения Webhooks

    +
    + + + +
    + +
      + {webhooks.map((webhook, index) => ( +
    • + Webhook: {webhook.url} (Группы: {webhook.groups.join(', ')}) +
    • + ))} +
    +
    + + {/* WebSocket подключение */} +
    +

    Подключения WebSockets

    +
    { + e.preventDefault(); + setWebsocketUrl(e.target.websocketUrl.value); + }} + > + + +
    + + {websocketUrl &&

    Подключено по WebSocket: {websocketUrl}

    } +
    +
    + ); +}; + +export default Connections; \ No newline at end of file diff --git a/src/pages/Login.js b/src/pages/Login.js index 0fb96cb..a6b2673 100644 --- a/src/pages/Login.js +++ b/src/pages/Login.js @@ -1,42 +1,52 @@ import React, { useState } from 'react'; -import './Login.css'; +import '../Login.scss'; 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('Неверный логин или пароль'); - } + const [username, setUsername] = useState(''); + const [password, setPassword] = useState(''); + const [error, setError] = useState(''); + + const handleSubmit = (e) => { + e.preventDefault(); + // Simple login/password check + if (username === 'admin' && password === 'admin') { + onLogin(); // Call function on successful login + } else { + setError('Неверный логин или пароль'); + } + }; + + return ( +
    +
    {/* Added a wrapper for styling */} +

    Вход

    + {error &&

    {error}

    } +
    +
    + + setUsername(e.target.value)} + /> +
    +
    + + setPassword(e.target.value)} + /> +
    + +
    +
    +
    + ); }; - - return ( -
    -
    -

    Вход

    - {error &&

    {error}

    } - setUsername(e.target.value)} - /> - setPassword(e.target.value)} - /> - -
    -
    - ); -}; - -export default Login; \ No newline at end of file + + export default Login; \ No newline at end of file