glistik v popke

This commit is contained in:
gotika 2024-09-21 18:39:58 +03:00
parent 55215cb47c
commit 93818c3a3e
8 changed files with 349 additions and 270 deletions

View File

@ -1,23 +1,24 @@
import React from "react";
import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
import React, { useState } from 'react';
import DeviceGroups from "./pages/DeviceGroups";
import Devices from "./pages/Devices";
import Sidebar from "./Sidebar";
import Dashboard from "./pages/Dashboard";
import DevicesPage from "./pages/DevicesPage"; // Добавляем страницу для управления устройствами
import Dashboard from './pages/Dashboard';
const App = () => {
const [activeTab, setActiveTab] = useState('map'); // По умолчанию активная вкладка "Карта"
return (
<Router>
<div style={{ display: "flex", height: "100vh" }}>
<Sidebar />
<div style={{ flex: 1, padding: "20px" }}>
<Routes>
<Route path="/" element={<Dashboard />} /> {/* Главная страница с картой */}
<Route path="/devices" element={<DevicesPage />} /> {/* Страница управления устройствами */}
</Routes>
</div>
<div style={{ display: 'flex' }}>
<Sidebar onSelectTab={setActiveTab} activeTab={activeTab} /> {/* Передаем активную вкладку */}
<div style={{ padding: '20px', flex: 1 }}>
{activeTab === 'map' && <Dashboard />} {/* Подключаем компонент Dashboard */}
{activeTab === 'connection' && <div>Подключение</div>}
{activeTab === 'account' && <div>Аккаунт пользователя</div>}
{activeTab === 'groups' && <DeviceGroups />} {/* Группы устройств */}
{activeTab === 'devices' && <Devices />} {/* Устройства */}
</div>
</Router>
</div>
);
};
export default App;
export default App;

48
src/DeviceGroups.css Normal file
View File

@ -0,0 +1,48 @@
.device-groups {
padding: 20px;
}
.device-groups h2 {
margin-bottom: 20px;
}
.group-creation {
margin-bottom: 20px;
}
.group-creation input {
padding: 5px;
margin-right: 10px;
}
.group-creation button {
padding: 5px 10px;
}
ul {
list-style-type: none;
padding: 0;
}
li {
margin-bottom: 20px;
padding: 10px;
border: 1px solid #ddd;
border-radius: 5px;
}
.active {
background-color: #e8f5e9;
}
.inactive {
background-color: #ffebee;
}
li div {
margin-bottom: 10px;
}
li button {
margin-right: 10px;
}

38
src/Devices.css Normal file
View File

@ -0,0 +1,38 @@
.devices {
padding: 20px;
}
.devices h2 {
margin-bottom: 20px;
}
.devices table {
width: 100%;
border-collapse: collapse;
}
.devices table, .devices th, .devices td {
border: 1px solid #ddd;
}
.devices th, .devices td {
padding: 8px;
text-align: left;
}
.devices th {
background-color: #34495e;
color: white;
}
.devices tr:hover {
background-color: #f1f1f1;
}
.buttons {
margin-top: 20px;
}
.buttons button {
margin-right: 10px;
}

View File

@ -1,29 +1,50 @@
.sidebar {
width: 250px;
height: 100vh;
background-color: #2c3e50;
color: white;
padding: 20px;
box-shadow: 2px 0 5px rgba(0, 0, 0, 0.5);
}
.sidebar h2 {
font-size: 24px;
margin-bottom: 20px;
}
.sidebar ul {
list-style-type: none;
padding: 0;
}
.sidebar li {
margin: 15px 0;
cursor: pointer;
}
.sidebar li:hover {
background-color: #34495e;
padding: 10px;
border-radius: 5px;
}
width: 250px;
height: 100vh;
background-color: #2c3e50;
color: white;
padding: 20px;
box-shadow: 2px 0 5px rgba(0, 0, 0, 0.5);
}
.sidebar h2 {
font-size: 24px;
margin-bottom: 20px;
}
.sidebar ul {
list-style-type: none;
padding: 0;
}
.sidebar li {
margin: 15px 0;
cursor: pointer;
}
.sidebar li:hover {
background-color: #34495e;
padding: 10px;
border-radius: 5px;
}
.sidebar ul {
list-style-type: none;
padding: 0;
}
.sidebar li {
margin: 15px 0;
cursor: pointer;
padding: 10px;
border-radius: 5px;
transition: background-color 0.3s;
}
.sidebar li:hover {
background-color: #34495e;
}
.sidebar li.active {
background-color: #2980b9;
color: white;
}

View File

@ -1,58 +1,29 @@
import React from "react";
import { Link } from "react-router-dom";
import React from 'react';
import './Sidebar.css';
const Sidebar = () => {
const Sidebar = ({ onSelectTab, activeTab }) => {
return (
<div style={styles.sidebar}>
<h2 style={styles.heading}>Навигация</h2>
<ul style={styles.list}>
<li style={styles.listItem}>
<Link to="/" style={styles.link}>Карта всех устройств</Link>
<div className="sidebar">
<h2>Меню</h2>
<ul>
<li className={activeTab === 'map' ? 'active' : ''} onClick={() => onSelectTab('map')}>
Карта в реальном времени
</li>
<li style={styles.listItem}>
<Link to="/devices" style={styles.link}>Устройства</Link>
<li className={activeTab === 'connection' ? 'active' : ''} onClick={() => onSelectTab('connection')}>
Подключение
</li>
<li style={styles.listItem}>
<Link to="#" style={styles.link}>Группы устройств</Link>
<li className={activeTab === 'account' ? 'active' : ''} onClick={() => onSelectTab('account')}>
Аккаунт пользователя
</li>
<li className={activeTab === 'groups' ? 'active' : ''} onClick={() => onSelectTab('groups')}>
Группы устройств
</li>
<li className={activeTab === 'devices' ? 'active' : ''} onClick={() => onSelectTab('devices')}>
Устройства
</li>
</ul>
</div>
);
};
// Объект с инлайн-стилями
const styles = {
sidebar: {
width: '250px',
backgroundColor: '#2c3e50',
padding: '20px',
height: '100vh',
color: 'white',
boxShadow: '2px 0 5px rgba(0, 0, 0, 0.1)',
},
heading: {
fontSize: '24px',
marginBottom: '20px',
color: '#ecf0f1',
borderBottom: '2px solid #34495e',
paddingBottom: '10px',
},
list: {
listStyleType: 'none',
padding: '0',
},
listItem: {
marginBottom: '15px',
},
link: {
color: '#ecf0f1',
textDecoration: 'none',
fontSize: '18px',
display: 'block',
padding: '10px',
borderRadius: '4px',
transition: 'background-color 0.3s',
},
};
export default Sidebar;

87
src/pages/DeviceGroups.js Normal file
View File

@ -0,0 +1,87 @@
import React, { useState } from 'react';
import '../DeviceGroups.css';
const DeviceGroups = () => {
const [groups, setGroups] = useState([]);
const [newGroupName, setNewGroupName] = useState('');
const createGroup = () => {
if (newGroupName) {
const newGroup = {
name: newGroupName,
devices: [],
active: true,
};
setGroups([...groups, newGroup]);
setNewGroupName('');
}
};
const deleteGroup = (groupName) => {
setGroups(groups.filter(group => group.name !== groupName));
};
const toggleGroupStatus = (groupName) => {
setGroups(groups.map(group =>
group.name === groupName ? { ...group, active: !group.active } : group
));
};
const addDeviceToGroup = (groupName, device) => {
setGroups(groups.map(group =>
group.name === groupName ? { ...group, devices: [...group.devices, device] } : group
));
};
const removeDeviceFromGroup = (groupName, device) => {
setGroups(groups.map(group =>
group.name === groupName ? { ...group, devices: group.devices.filter(d => d !== device) } : group
));
};
return (
<div className="device-groups">
<h2>Группы устройств</h2>
<div className="group-creation">
<input
type="text"
value={newGroupName}
onChange={(e) => setNewGroupName(e.target.value)}
placeholder="Название новой группы"
/>
<button onClick={createGroup}>Создать группу</button>
</div>
<ul>
{groups.map(group => (
<li key={group.name} className={group.active ? 'active' : 'inactive'}>
<div>
<span>{group.name}</span>
<button onClick={() => deleteGroup(group.name)}>Удалить</button>
<button onClick={() => toggleGroupStatus(group.name)}>
{group.active ? 'Деактивировать' : 'Активировать'}
</button>
</div>
<div>
<h4>Устройства в группе:</h4>
<ul>
{group.devices.map((device, index) => (
<li key={index}>
{device} <button onClick={() => removeDeviceFromGroup(group.name, device)}>Удалить</button>
</li>
))}
</ul>
<button onClick={() => addDeviceToGroup(group.name, 'Новое устройство')}>
Добавить устройство
</button>
</div>
</li>
))}
</ul>
</div>
);
};
export default DeviceGroups;

93
src/pages/Devices.js Normal file
View File

@ -0,0 +1,93 @@
import React, { useState } from 'react';
import { QRCodeCanvas } from "qrcode.react";
import '../Devices.css';
const Devices = () => {
const [devices, setDevices] = useState([]);
const [selectedDevice, setSelectedDevice] = useState(null);
const [deviceName, setDeviceName] = useState('');
const [deviceStatus, setDeviceStatus] = useState('');
const addDevice = () => {
if (deviceName) {
const newDevice = { name: deviceName, status: deviceStatus || 'Неактивен', id: Date.now() };
setDevices([...devices, newDevice]);
setDeviceName('');
setDeviceStatus('');
}
};
const removeDevice = () => {
if (selectedDevice) {
setDevices(devices.filter(device => device.id !== selectedDevice.id));
setSelectedDevice(null);
}
};
const editDevice = () => {
if (selectedDevice) {
const updatedDevices = devices.map(device =>
device.id === selectedDevice.id
? { ...device, name: deviceName, status: deviceStatus }
: device
);
setDevices(updatedDevices);
setSelectedDevice(null);
setDeviceName('');
setDeviceStatus('');
}
};
const generateQR = (device) => {
return (
<QRCodeCanvas value={JSON.stringify(device)} size={128} />
);
};
return (
<div className="devices">
<h2>Устройства</h2>
<input
type="text"
placeholder="Название устройства"
value={deviceName}
onChange={(e) => setDeviceName(e.target.value)}
/>
<input
type="text"
placeholder="Статус устройства"
value={deviceStatus}
onChange={(e) => setDeviceStatus(e.target.value)}
/>
<table>
<thead>
<tr>
<th>Название</th>
<th>Статус</th>
<th>QR Код</th>
<th>Действия</th>
</tr>
</thead>
<tbody>
{devices.map((device) => (
<tr key={device.id} onClick={() => setSelectedDevice(device)}>
<td>{device.name}</td>
<td>{device.status}</td>
<td>{generateQR(device)}</td>
<td>
<button onClick={editDevice}>Редактировать</button>
</td>
</tr>
))}
</tbody>
</table>
<div className="buttons">
<button onClick={addDevice}>Добавить</button>
<button onClick={removeDevice} disabled={!selectedDevice}>Удалить выбранное</button>
<button onClick={editDevice} disabled={!selectedDevice}>Сохранить изменения</button>
</div>
</div>
);
};
export default Devices;

View File

@ -1,180 +0,0 @@
import React, { useState } from "react";
import { QRCodeCanvas } from "qrcode.react";
const DevicesPage = () => {
const [devices, setDevices] = useState([]);
const [newDeviceName, setNewDeviceName] = useState("");
const [editDeviceId, setEditDeviceId] = useState(null);
const [editDeviceName, setEditDeviceName] = useState("");
const addDevice = () => {
if (newDeviceName) {
setDevices([...devices, { name: newDeviceName, id: Date.now() }]);
setNewDeviceName("");
}
};
const removeDevice = (id) => {
setDevices(devices.filter((device) => device.id !== id));
};
const startEditDevice = (device) => {
setEditDeviceId(device.id);
setEditDeviceName(device.name);
};
const saveDeviceEdit = () => {
setDevices(
devices.map((device) =>
device.id === editDeviceId ? { ...device, name: editDeviceName } : device
)
);
setEditDeviceId(null);
setEditDeviceName("");
};
return (
<div style={styles.container}>
<h1 style={styles.title}>Устройства</h1>
<div style={styles.addDevice}>
<input
type="text"
value={newDeviceName}
onChange={(e) => setNewDeviceName(e.target.value)}
placeholder="Название нового устройства"
style={styles.input}
/>
<button onClick={addDevice} style={styles.addButton}>Добавить устройство</button>
</div>
<ul style={styles.deviceList}>
{devices.map((device) => (
<li key={device.id} style={styles.deviceItem}>
{editDeviceId === device.id ? (
<div style={styles.editContainer}>
<input
type="text"
value={editDeviceName}
onChange={(e) => setEditDeviceName(e.target.value)}
placeholder="Новое имя устройства"
style={styles.input}
/>
<button onClick={saveDeviceEdit} style={styles.saveButton}>Сохранить</button>
<button onClick={() => setEditDeviceId(null)} style={styles.cancelButton}>Отмена</button>
</div>
) : (
<>
<b style={styles.deviceName}>{device.name}</b>
<button onClick={() => startEditDevice(device)} style={styles.editButton}>
Редактировать
</button>
<button onClick={() => removeDevice(device.id)} style={styles.deleteButton}>
Удалить
</button>
{/* Генерация QR-кода для устройства */}
<QRCodeCanvas value={`Device ID: ${device.id}, Device Name: ${device.name}`} />
</>
)}
</li>
))}
</ul>
</div>
);
};
const styles = {
container: {
padding: "20px",
backgroundColor: "#f5f5f5",
borderRadius: "8px",
boxShadow: "0 2px 10px rgba(0, 0, 0, 0.1)",
},
title: {
marginBottom: "20px",
color: "#333",
},
addDevice: {
marginBottom: "20px",
display: "flex",
alignItems: "center",
},
input: {
padding: "10px",
marginRight: "10px",
border: "1px solid #ccc",
borderRadius: "4px",
flexGrow: 1,
},
addButton: {
padding: "10px 15px",
backgroundColor: "#3498db",
color: "white",
border: "none",
borderRadius: "4px",
cursor: "pointer",
transition: "background-color 0.3s",
},
addButtonHover: {
backgroundColor: "#2980b9",
},
deviceList: {
listStyleType: "none",
padding: "0",
},
deviceItem: {
backgroundColor: "white",
borderRadius: "5px",
padding: "15px",
marginBottom: "10px",
boxShadow: "0 1px 5px rgba(0, 0, 0, 0.1)",
display: "flex",
alignItems: "center",
justifyContent: "space-between",
},
editContainer: {
display: "flex",
alignItems: "center",
},
deviceName: {
flexGrow: 1,
fontWeight: "bold",
},
editButton: {
marginLeft: "10px",
padding: "5px 10px",
backgroundColor: "#f39c12",
color: "white",
border: "none",
borderRadius: "4px",
cursor: "pointer",
},
deleteButton: {
marginLeft: "10px",
padding: "5px 10px",
backgroundColor: "#e74c3c",
color: "white",
border: "none",
borderRadius: "4px",
cursor: "pointer",
},
saveButton: {
marginLeft: "10px",
padding: "5px 10px",
backgroundColor: "#2ecc71",
color: "white",
border: "none",
borderRadius: "4px",
cursor: "pointer",
},
cancelButton: {
marginLeft: "10px",
padding: "5px 10px",
backgroundColor: "#95a5a6",
color: "white",
border: "none",
borderRadius: "4px",
cursor: "pointer",
},
};
export default DevicesPage;