Karmashek commited on
Commit
d1d360c
·
verified ·
1 Parent(s): e25f871

Add 3 files

Browse files
Files changed (3) hide show
  1. README.md +6 -4
  2. index.html +475 -18
  3. prompts.txt +0 -0
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Bad1
3
- emoji: 🏢
4
  colorFrom: red
5
- colorTo: blue
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: bad1
3
+ emoji: 🐳
4
  colorFrom: red
5
+ colorTo: red
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,476 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  </html>
 
1
+ <!DOCTYPE html>
2
+ <html lang="ru">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
6
+ <title>MES System</title>
7
+ <script src="https://cdn.tailwindcss.com "></script>
8
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css "/>
9
+ <style>
10
+ .notification-badge {
11
+ position: absolute;
12
+ top: 0;
13
+ right: 0;
14
+ font-size: 0.625rem;
15
+ line-height: 1.25rem;
16
+ width: 1.25rem;
17
+ height: 1.25rem;
18
+ display: flex;
19
+ align-items: center;
20
+ justify-content: center;
21
+ border-radius: 9999px;
22
+ }
23
+ .has-event:hover {
24
+ background-color: #BFDBFE !important;
25
+ }
26
+ </style>
27
+ </head>
28
+ <body class="bg-gray-50 text-white font-sans">
29
+
30
+ <div id="app" class="flex h-screen overflow-hidden bg-gray-50"></div>
31
+
32
+ <script type="module">
33
+ import { createRoot } from 'https://unpkg.com/react @18/umd/react.development.js';
34
+ import ReactDOM from 'https://unpkg.com/react-dom @18/umd/react-dom.development.js';
35
+
36
+ const root = ReactDOM.createRoot(document.getElementById('app'));
37
+
38
+ // Mock data
39
+ const equipmentData = [
40
+ {
41
+ id: 1,
42
+ name: "Токарный станок CNC-2000",
43
+ type: "Станок",
44
+ serial: "CNC2000-001",
45
+ inventory: "INV-1001",
46
+ status: "active",
47
+ lastMaintenance: "2023-05-15",
48
+ nextMaintenance: "2023-06-15",
49
+ maintenanceInterval: 30,
50
+ description: "Токарный станок с ЧПУ"
51
+ },
52
+ {
53
+ id: 2,
54
+ name: "Конвейерная линия A-12",
55
+ type: "Конвейер",
56
+ serial: "CONV-A12-045",
57
+ inventory: "INV-1042",
58
+ status: "maintenance",
59
+ lastMaintenance: "2023-05-20",
60
+ nextMaintenance: "2023-06-20",
61
+ maintenanceInterval: 30,
62
+ description: "Линия для сборки продукции"
63
+ },
64
+ {
65
+ id: 3,
66
+ name: "Воздушный компрессор V-50",
67
+ type: "Компрессор",
68
+ serial: "COMP-V50-112",
69
+ inventory: "INV-1078",
70
+ status: "repair",
71
+ lastMaintenance: "2023-04-10",
72
+ nextMaintenance: "2023-06-10",
73
+ maintenanceInterval: 60,
74
+ description: "Промышленный воздушный компрессор"
75
+ }
76
+ ];
77
+
78
+ const users = [
79
+ {id: 1, name: "Иван Петров", role: "admin", email: "ivan@example.com"},
80
+ {id: 2, name: "Петр Смирнов", role: "engineer", email: "petr@example.com"},
81
+ {id: 3, name: "Анна Иванова", role: "viewer", email: "anna@example.com"}
82
+ ];
83
+
84
+ const maintenanceEvents = [
85
+ {equipmentId: 1, date: "2023-06-15", status: "planned", responsible: "Иванов А.П."},
86
+ {equipmentId: 2, date: "2023-06-20", status: "planned", responsible: "Петров И.С."},
87
+ {equipmentId: 3, date: "2023-06-10", status: "overdue", responsible: "Сидоров В.М."}
88
+ ];
89
+
90
+ function formatDate(dateStr) {
91
+ if (!dateStr) return "";
92
+ const d = new Date(dateStr);
93
+ return `${d.getDate()}.${d.getMonth()+1}.${d.getFullYear()}`;
94
+ }
95
+
96
+ function calculateNextMaintenanceDate(commissionDate, intervalDays) {
97
+ if (!commissionDate) return '';
98
+ const nextDate = new Date(new Date(commissionDate).getTime() + parseInt(intervalDays) * 24 * 60 * 60 * 1000);
99
+ return nextDate.toISOString().split('T')[0];
100
+ }
101
+
102
+ function Dashboard({ setActiveTab }) {
103
+ const activeCount = equipmentData.length;
104
+ const completedCount = equipmentData.filter(e => e.lastMaintenance).length;
105
+ const overdueCount = equipmentData.filter(e => new Date(e.nextMaintenance) < new Date()).length;
106
+ const repairCount = equipmentData.filter(e => e.status === "repair").length;
107
+
108
+ return (
109
+ <div class="p-6">
110
+ <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-6">
111
+ <div class="bg-white rounded-lg shadow p-6 text-gray-800">
112
+ <div class="flex items-center">
113
+ <i class="fas fa-tools text-xl text-blue-500 mr-4"></i>
114
+ <div>
115
+ <p class="text-sm text-gray-500">Всего оборудования</p>
116
+ <h3 class="text-2xl font-bold">{activeCount}</h3>
117
+ </div>
118
+ </div>
119
+ </div>
120
+ <div class="bg-white rounded-lg shadow p-6 text-gray-800">
121
+ <div class="flex items-center">
122
+ <i class="fas fa-check-circle text-xl text-green-500 mr-4"></i>
123
+ <div>
124
+ <p class="text-sm text-gray-500">Выполнено ТО</p>
125
+ <h3 class="text-2xl font-bold">{completedCount}</h3>
126
+ </div>
127
+ </div>
128
+ </div>
129
+ <div class="bg-white rounded-lg shadow p-6 text-gray-800">
130
+ <div class="flex items-center">
131
+ <i class="fas fa-exclamation-triangle text-xl text-yellow-500 mr-4"></i>
132
+ <div>
133
+ <p class="text-sm text-gray-500">Просрочено ТО</p>
134
+ <h3 class="text-2xl font-bold">{overdueCount}</h3>
135
+ </div>
136
+ </div>
137
+ </div>
138
+ <div class="bg-white rounded-lg shadow p-6 text-gray-800">
139
+ <div class="flex items-center">
140
+ <i class="fas fa-wrench text-xl text-red-500 mr-4"></i>
141
+ <div>
142
+ <p class="text-sm text-gray-500">Текущие ремонты</p>
143
+ <h3 class="text-2xl font-bold">{repairCount}</h3>
144
+ </div>
145
+ </div>
146
+ </div>
147
+ </div>
148
+
149
+ <div class="bg-white rounded-lg shadow overflow-hidden">
150
+ <div class="p-4 border-b flex justify-between items-center">
151
+ <h2 class="text-lg font-semibold">Оборудование</h2>
152
+ <button onClick={() => setActiveTab("equipment")} class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg flex items-center">
153
+ <i class="fas fa-plus mr-2"></i> Перейти к оборудованию
154
+ </button>
155
+ </div>
156
+ <div class="overflow-x-auto">
157
+ <table class="min-w-full divide-y divide-gray-200">
158
+ <thead class="bg-gray-50">
159
+ <tr>
160
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">ID</th>
161
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Название</th>
162
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Тип</th>
163
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Статус</th>
164
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Последнее ТО</th>
165
+ </tr>
166
+ </thead>
167
+ <tbody class="bg-white divide-y divide-gray-200">
168
+ {equipmentData.map(eq => (
169
+ <tr key={eq.id}>
170
+ <td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">{eq.id}</td>
171
+ <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">{eq.name}</td>
172
+ <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">{eq.type}</td>
173
+ <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
174
+ <span class={`px-2 py-1 rounded-full text-xs font-semibold ${
175
+ eq.status === "active" ? "bg-green-100 text-green-800" :
176
+ eq.status === "maintenance" ? "bg-yellow-100 text-yellow-800" : "bg-red-100 text-red-800"
177
+ }`}>
178
+ {eq.status === "active" ? "Активно" : eq.status === "maintenance" ? "ТО" : "Ремонт"}
179
+ </span>
180
+ </td>
181
+ <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">{formatDate(eq.lastMaintenance)}</td>
182
+ </tr>
183
+ ))}
184
+ </tbody>
185
+ </table>
186
+ </div>
187
+ </div>
188
+ </div>
189
+ );
190
+ }
191
+
192
+ function Equipment({ setEquipmentList, setActiveTab }) {
193
+ const [showModal, setShowModal] = React.useState(false);
194
+ const [newEq, setNewEq] = React.useState({
195
+ name: "",
196
+ type: "",
197
+ serial: "",
198
+ inventory: "",
199
+ commissionDate: "",
200
+ maintenanceInterval: 30,
201
+ description: ""
202
+ });
203
+
204
+ const handleAdd = () => {
205
+ if (!newEq.name || !newEq.type || !newEq.serial || !newEq.inventory || !newEq.commissionDate) {
206
+ alert("Заполните все обязательные поля");
207
+ return;
208
+ }
209
+
210
+ const id = equipmentData.length > 0 ? Math.max(...equipmentData.map(e => e.id)) + 1 : 1;
211
+ equipmentData.push({
212
+ ...newEq,
213
+ id,
214
+ status: "active",
215
+ nextMaintenance: calculateNextMaintenanceDate(newEq.commissionDate, newEq.maintenanceInterval)
216
+ });
217
+ setEquipmentList([...equipmentData]);
218
+ setShowModal(false);
219
+ alert("Оборудование добавлено");
220
+ };
221
+
222
+ return (
223
+ <div class="p-6">
224
+ <h2 class="text-2xl font-bold mb-6">Оборудование</h2>
225
+ <div class="bg-white rounded-lg shadow overflow-hidden">
226
+ <div class="p-4 border-b flex justify-between items-center">
227
+ <h3 class="text-lg font-semibold">Список оборудования</h3>
228
+ <button onClick={() => setShowModal(true)} class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg flex items-center">
229
+ <i class="fas fa-plus mr-2"></i> Добавить
230
+ </button>
231
+ </div>
232
+ <div class="overflow-x-auto">
233
+ <table class="min-w-full divide-y divide-gray-200">
234
+ <thead class="bg-gray-50">
235
+ <tr>
236
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase">ID</th>
237
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase">Название</th>
238
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase">Тип</th>
239
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase">Статус</th>
240
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase">Последнее ТО</th>
241
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase">Действия</th>
242
+ </tr>
243
+ </thead>
244
+ <tbody class="bg-white divide-y divide-gray-200">
245
+ {equipmentData.map(eq => (
246
+ <tr key={eq.id}>
247
+ <td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">{eq.id}</td>
248
+ <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">{eq.name}</td>
249
+ <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">{eq.type}</td>
250
+ <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
251
+ <span class={`px-2 py-1 rounded-full text-xs font-semibold ${
252
+ eq.status === "active" ? "bg-green-100 text-green-800" :
253
+ eq.status === "maintenance" ? "bg-yellow-100 text-yellow-800" : "bg-red-100 text-red-800"
254
+ }`}>
255
+ {eq.status === "active" ? "Активно" : eq.status === "maintenance" ? "ТО" : "Ремонт"}
256
+ </span>
257
+ </td>
258
+ <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">{formatDate(eq.lastMaintenance)}</td>
259
+ <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
260
+ <button class="text-blue-600 hover:text-blue-900 mr-3"><i class="fas fa-edit"></i></button>
261
+ <button class="text-red-600 hover:text-red-900"><i class="fas fa-trash"></i></button>
262
+ </td>
263
+ </tr>
264
+ ))}
265
+ </tbody>
266
+ </table>
267
+ </div>
268
+ </div>
269
+
270
+ {showModal && (
271
+ <div class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
272
+ <div class="bg-white rounded-lg w-full max-w-md p-6">
273
+ <div class="flex justify-between items-center mb-4">
274
+ <h3 class="text-lg font-semibold">Добавить оборудование</h3>
275
+ <button onClick={() => setShowModal(false)} class="text-gray-500">&times;</button>
276
+ </div>
277
+ <form class="space-y-4">
278
+ <input value={newEq.name} onInput={(e) => setNewEq({...newEq, name: e.target.value})} placeholder="Название" required class="w-full px-4 py-2 border rounded-lg"/>
279
+ <select value={newEq.type} onChange={(e) => setNewEq({...newEq, type: e.target.value})} required class="w-full px-4 py-2 border rounded-lg">
280
+ <option value="">Выберите тип</option>
281
+ <option>Станок</option>
282
+ <option>Конвейер</option>
283
+ <option>Компрессор</option>
284
+ <option>Генератор</option>
285
+ <option>Насос</option>
286
+ </select>
287
+ <input value={newEq.serial} onInput={(e) => setNewEq({...newEq, serial: e.target.value})} placeholder="Серийный номер" required class="w-full px-4 py-2 border rounded-lg"/>
288
+ <input value={newEq.inventory} onInput={(e) => setNewEq({...newEq, inventory: e.target.value})} placeholder="Инвентарный номер" required class="w-full px-4 py-2 border rounded-lg"/>
289
+ <input value={newEq.commissionDate} type="date" onInput={(e) => setNewEq({...newEq, commissionDate: e.target.value})} required class="w-full px-4 py-2 border rounded-lg"/>
290
+ <input value={newEq.maintenanceInterval} type="number" min="1" onInput={(e) => setNewEq({...newEq, maintenanceInterval: e.target.value})} placeholder="Интервал ТО (дни)" required class="w-full px-4 py-2 border rounded-lg"/>
291
+ <textarea value={newEq.description} onInput={(e) => setNewEq({...newEq, description: e.target.value})} rows="3" placeholder="Описание" class="w-full px-4 py-2 border rounded-lg"></textarea>
292
+ </form>
293
+ <div class="mt-4 flex justify-end space-x-2">
294
+ <button onClick={() => setShowModal(false)} class="px-4 py-2 border rounded-lg hover:bg-gray-100">Отмена</button>
295
+ <button onClick={handleAdd} class="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700">Сохранить</button>
296
+ </div>
297
+ </div>
298
+ </div>
299
+ )}
300
+ </div>
301
+ );
302
+ }
303
+
304
+ function Schedule() {
305
+ return (
306
+ <div class="p-6">
307
+ <h2 class="text-2xl font-bold mb-6">График ТО</h2>
308
+ <div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
309
+ <div class="lg:col-span-2 bg-white rounded-lg shadow p-4">
310
+ <h3 class="text-lg font-semibold mb-4">Календарь ТО</h3>
311
+ <div class="flex justify-between items-center mb-4">
312
+ <h4 class="font-medium">Июнь 2023</h4>
313
+ <div class="flex space-x-2">
314
+ <button class="p-2 rounded-full hover:bg-gray-100"><i class="fas fa-chevron-left"></i></button>
315
+ <button class="p-2 rounded-full hover:bg-gray-100"><i class="fas fa-chevron-right"></i></button>
316
+ </div>
317
+ </div>
318
+ <div class="grid grid-cols-7 gap-1 mb-2">
319
+ {['Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб', 'Вс'].map(day => (
320
+ <div class="text-center text-xs font-medium text-gray-500">{day}</div>
321
+ ))}
322
+ </div>
323
+ <div class="grid grid-cols-7 gap-1">
324
+ {[...Array(35)].map((_, i) => {
325
+ const day = i - 4;
326
+ const hasEvent = maintenanceEvents.some(event => new Date(event.date).getDate() === day && new Date(event.date).getMonth() === 5);
327
+ return (
328
+ <div class={`h-10 flex items-center justify-center border rounded ${hasEvent ? 'bg-blue-50' : ''}>{day > 0 && day <= 30 ? day : ''}</div>
329
+ );
330
+ })}
331
+ </div>
332
+ </div>
333
+ </div>
334
+ </div>
335
+ );
336
+ }
337
+
338
+ function Users() {
339
+ return (
340
+ <div class="p-6">
341
+ <h2 class="text-2xl font-bold mb-6">Пользователи</h2>
342
+ <div class="bg-white rounded-lg shadow overflow-hidden">
343
+ <div class="p-4 border-b">
344
+ <h3 class="text-lg font-semibold">Список пользователей</h3>
345
+ </div>
346
+ <div class="overflow-x-auto">
347
+ <table class="min-w-full divide-y divide-gray-200">
348
+ <thead class="bg-gray-50">
349
+ <tr>
350
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase">Имя</th>
351
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase">Email</th>
352
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase">Роль</th>
353
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase">Действия</th>
354
+ </tr>
355
+ </thead>
356
+ <tbody class="bg-white divide-y divide-gray-200">
357
+ {users.map(user => (
358
+ <tr key={user.id}>
359
+ <td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">{user.name}</td>
360
+ <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">{user.email}</td>
361
+ <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
362
+ <span class={`px-2 py-1 rounded-full text-xs font-semibold ${
363
+ user.role === "admin" ? "bg-purple-100 text-purple-800" :
364
+ user.role === "engineer" ? "bg-blue-100 text-blue-800" : "bg-gray-100 text-gray-800"
365
+ }`}>
366
+ {user.role === "admin" ? "Администратор" : user.role === "engineer" ? "Инженер" : "Просмотр"}
367
+ </span>
368
+ </td>
369
+ <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
370
+ <button class="text-blue-600 hover:text-blue-900 mr-3"><i class="fas fa-edit"></i></button>
371
+ <button class="text-red-600 hover:text-red-900"><i class="fas fa-trash"></i></button>
372
+ </td>
373
+ </tr>
374
+ ))}
375
+ </tbody>
376
+ </table>
377
+ </div>
378
+ </div>
379
+ </div>
380
+ );
381
+ }
382
+
383
+ function App() {
384
+ const [activeTab, setActiveTab] = React.useState("dashboard");
385
+ const [isSidebarCollapsed, setIsSidebarCollapsed] = React.useState(false);
386
+
387
+ const renderContent = () => {
388
+ switch (activeTab) {
389
+ case "dashboard": return <Dashboard setActiveTab={setActiveTab}/>;
390
+ case "schedule": return <Schedule />;
391
+ case "equipment": return <Equipment setEquipmentList={setActiveTab} setActiveTab={setActiveTab}/>;
392
+ case "users": return <Users />;
393
+ default: return <Dashboard setActiveTab={setActiveTab}/>;
394
+ }
395
+ };
396
+
397
+ return (
398
+ <div class="flex h-screen overflow-hidden bg-gray-50">
399
+ {/* Sidebar */}
400
+ <div class={`sidebar bg-blue-800 text-white transition-all duration-300 ${isSidebarCollapsed ? 'collapsed w-16' : 'w-64'} flex flex-col`}>
401
+ <div class="p-4 flex items-center justify-between border-b border-blue-700">
402
+ <div class="flex items-center">
403
+ <i class="fas fa-cogs text-2xl mr-3"></i>
404
+ {!isSidebarCollapsed && <span class="text-xl font-bold">MES System</span>}
405
+ </div>
406
+ <button onClick={() => setIsSidebarCollapsed(!isSidebarCollapsed)} class="hover:text-blue-200">
407
+ <i class="fas fa-bars"></i>
408
+ </button>
409
+ </div>
410
+ <nav class="p-4 flex-1 overflow-y-auto">
411
+ <div class="mb-6">
412
+ <p class="uppercase text-xs font-semibold text-blue-300 mb-2">Основное</p>
413
+ <button onClick={() => setActiveTab("dashboard")} class={`flex items-center py-2 px-3 rounded-lg w-full text-left ${activeTab === "dashboard" ? "bg-blue-700" : "hover:bg-blue-700"} mb-2`}>
414
+ <i class="fas fa-tachometer-alt mr-3"></i>
415
+ {!isSidebarCollapsed && <span>Главная</span>}
416
+ </button>
417
+ <button onClick={() => setActiveTab("schedule")} class={`flex items-center py-2 px-3 rounded-lg w-full text-left ${activeTab === "schedule" ? "bg-blue-700" : "hover:bg-blue-700"} mb-2`}>
418
+ <i class="fas fa-calendar-alt mr-3"></i>
419
+ {!isSidebarCollapsed && <span>График ТО</span>}
420
+ </button>
421
+ <button onClick={() => setActiveTab("equipment")} class={`flex items-center py-2 px-3 rounded-lg w-full text-left ${activeTab === "equipment" ? "bg-blue-700" : "hover:bg-blue-700"} mb-2`}>
422
+ <i class="fas fa-tools mr-3"></i>
423
+ {!isSidebarCollapsed && <span>Оборудование</span>}
424
+ </button>
425
+ </div>
426
+ <div class="mb-6">
427
+ <p class="uppercase text-xs font-semibold text-blue-300 mb-2">Настройки</p>
428
+ <button onClick={() => setActiveTab("users")} class={`flex items-center py-2 px-3 rounded-lg w-full text-left ${activeTab === "users" ? "bg-blue-700" : "hover:bg-blue-700"} mb-2`}>
429
+ <i class="fas fa-users-cog mr-3"></i>
430
+ {!isSidebarCollapsed && <span>Пользователи</span>}
431
+ </button>
432
+ </div>
433
+ </nav>
434
+ <div class="p-4 border-t border-blue-700 flex items-center">
435
+ <img src="https://placehold.co/40x40?text=User " alt="User" class="w-10 h-10 rounded-full mr-3"/>
436
+ {!isSidebarCollapsed && (
437
+ <div>
438
+ <p class="font-medium">Иван Петров</p>
439
+ <p class="text-xs text-blue-300">Администратор</p>
440
+ </div>
441
+ )}
442
+ </div>
443
+ </div>
444
+
445
+ {/* Main Content */}
446
+ <div class="main-content flex-1 overflow-auto">
447
+ <header class="bg-white shadow-sm py-4 px-6 flex justify-between items-center">
448
+ <h1 class="text-2xl font-bold text-gray-800">
449
+ {activeTab === "dashboard" && "Главная панель"}
450
+ {activeTab === "schedule" && "График ТО"}
451
+ {activeTab === "equipment" && "Оборудование"}
452
+ {activeTab === "users" && "Пользователи"}
453
+ </h1>
454
+ <div class="flex items-center space-x-4">
455
+ <button class="p-2 rounded-full hover:bg-gray-100 relative">
456
+ <i class="fas fa-bell text-gray-600"></i>
457
+ <span class="notification-badge bg-red-500 text-white text-xs rounded-full h-5 w-5 flex items-center justify-center absolute top-0 right-0">5</span>
458
+ </button>
459
+ <div class="relative">
460
+ <input type="text" placeholder="Поиск..." class="pl-10 pr-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"/>
461
+ <i class="fas fa-search absolute left-3 top-3 text-gray-400"></i>
462
+ </div>
463
+ </div>
464
+ </header>
465
+ <div class="p-6">
466
+ {renderContent()}
467
+ </div>
468
+ </div>
469
+ </div>
470
+ );
471
+ }
472
+
473
+ root.render(<App />);
474
+ </script>
475
+ <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=Karmashek/bad1" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
476
  </html>
prompts.txt ADDED
File without changes