dandydow commited on
Commit
e73760b
·
verified ·
1 Parent(s): c8832f8

Add 3 files

Browse files
Files changed (3) hide show
  1. README.md +7 -5
  2. index.html +1047 -19
  3. prompts.txt +1 -0
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Backend Final Full
3
- emoji: 🐢
4
- colorFrom: pink
5
- colorTo: red
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: backend-final-full
3
+ emoji: 🐳
4
+ colorFrom: purple
5
+ colorTo: pink
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,1047 @@
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="pt-BR">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Painel de Controle - DeekSeek</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
9
+ <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
10
+ <style>
11
+ :root {
12
+ --bg-primary: #1a1a2e;
13
+ --bg-secondary: #16213e;
14
+ --text-primary: #e6e6e6;
15
+ --text-secondary: #b8b8b8;
16
+ --accent: #4f46e5;
17
+ --transition-speed: 0.3s;
18
+ }
19
+
20
+ .light {
21
+ --bg-primary: #f8fafc;
22
+ --bg-secondary: #ffffff;
23
+ --text-primary: #1e293b;
24
+ --text-secondary: #64748b;
25
+ }
26
+
27
+ body {
28
+ background-color: var(--bg-primary);
29
+ color: var(--text-primary);
30
+ transition: all var(--transition-speed) ease;
31
+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
32
+ }
33
+
34
+ .sidebar {
35
+ background-color: var(--bg-secondary);
36
+ border-right: 1px solid rgba(255, 255, 255, 0.1);
37
+ }
38
+
39
+ .card {
40
+ background-color: var(--bg-secondary);
41
+ border: 1px solid rgba(255, 255, 255, 0.1);
42
+ transition: transform 0.2s ease, box-shadow 0.2s ease;
43
+ border-radius: 0.5rem;
44
+ }
45
+
46
+ .card:hover {
47
+ transform: translateY(-2px);
48
+ box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.2);
49
+ }
50
+
51
+ .loading-spinner {
52
+ animation: spin 1s linear infinite;
53
+ }
54
+
55
+ @keyframes spin {
56
+ 0% { transform: rotate(0deg); }
57
+ 100% { transform: rotate(360deg); }
58
+ }
59
+
60
+ @media (max-width: 768px) {
61
+ .sidebar {
62
+ width: 100%;
63
+ position: fixed;
64
+ z-index: 40;
65
+ height: auto;
66
+ bottom: 0;
67
+ left: 0;
68
+ right: 0;
69
+ border-right: none;
70
+ border-top: 1px solid rgba(255, 255, 255, 0.1);
71
+ }
72
+
73
+ .sidebar-nav {
74
+ display: flex;
75
+ overflow-x: auto;
76
+ }
77
+
78
+ .sidebar-nav ul {
79
+ display: flex;
80
+ flex-direction: row;
81
+ }
82
+
83
+ .sidebar-nav li {
84
+ margin-right: 0.5rem;
85
+ }
86
+
87
+ .sidebar-nav button {
88
+ padding: 0.5rem;
89
+ white-space: nowrap;
90
+ }
91
+
92
+ .sidebar-nav i {
93
+ margin-right: 0;
94
+ }
95
+
96
+ .sidebar-nav span {
97
+ display: none;
98
+ }
99
+
100
+ .user-profile {
101
+ display: none;
102
+ }
103
+
104
+ main {
105
+ padding-bottom: 80px;
106
+ }
107
+ }
108
+ </style>
109
+ </head>
110
+ <body class="dark">
111
+ <div id="root"></div>
112
+
113
+ <script>
114
+ // Configuração da API
115
+ const API_BASE_URL = 'http://localhost:3000/api';
116
+
117
+ // Serviços de API
118
+ const ApiService = {
119
+ async getNews() {
120
+ try {
121
+ const response = await axios.get(`${API_BASE_URL}/news`);
122
+ return response.data;
123
+ } catch (error) {
124
+ console.error('Erro ao buscar notícias:', error);
125
+ return [];
126
+ }
127
+ },
128
+
129
+ async getAlerts() {
130
+ try {
131
+ const response = await axios.get(`${API_BASE_URL}/alerts`);
132
+ return response.data;
133
+ } catch (error) {
134
+ console.error('Erro ao buscar alertas:', error);
135
+ return [];
136
+ }
137
+ },
138
+
139
+ async postReport(reportData) {
140
+ try {
141
+ const response = await axios.post(`${API_BASE_URL}/denuncias`, reportData);
142
+ return response.data;
143
+ } catch (error) {
144
+ console.error('Erro ao enviar denúncia:', error);
145
+ throw error;
146
+ }
147
+ },
148
+
149
+ async getDashboardData() {
150
+ try {
151
+ const response = await axios.get(`${API_BASE_URL}/dashboard`);
152
+ return response.data;
153
+ } catch (error) {
154
+ console.error('Erro ao buscar dados do dashboard:', error);
155
+ return null;
156
+ }
157
+ }
158
+ };
159
+
160
+ // Componentes reutilizáveis
161
+ const Button = ({ children, icon, onClick, variant = 'primary', size = 'md', className = '', disabled = false }) => {
162
+ const baseClasses = 'flex items-center justify-center rounded-lg font-medium transition-all';
163
+ const sizeClasses = {
164
+ sm: 'px-3 py-1 text-sm',
165
+ md: 'px-4 py-2',
166
+ lg: 'px-6 py-3'
167
+ };
168
+ const variantClasses = {
169
+ primary: 'bg-indigo-600 hover:bg-indigo-700 text-white',
170
+ secondary: 'bg-gray-700 hover:bg-gray-600 text-white',
171
+ success: 'bg-green-600 hover:bg-green-700 text-white',
172
+ danger: 'bg-red-600 hover:bg-red-700 text-white',
173
+ warning: 'bg-yellow-600 hover:bg-yellow-700 text-white',
174
+ ghost: 'bg-transparent hover:bg-gray-700/50 text-white'
175
+ };
176
+
177
+ return `
178
+ <button
179
+ onclick="${onClick}"
180
+ ${disabled ? 'disabled' : ''}
181
+ class="${baseClasses} ${sizeClasses[size]} ${variantClasses[variant]} ${className}"
182
+ >
183
+ ${icon ? `<i class="${icon} ${children ? 'mr-2' : ''}"></i>` : ''}
184
+ ${children || ''}
185
+ </button>
186
+ `;
187
+ };
188
+
189
+ const Card = ({ children, title, className = '', headerClassName = '', bodyClassName = '' }) => {
190
+ return `
191
+ <div class="card ${className}">
192
+ ${title ? `
193
+ <div class="border-b border-gray-700 p-4 ${headerClassName}">
194
+ <h3 class="font-semibold">${title}</h3>
195
+ </div>
196
+ ` : ''}
197
+ <div class="p-4 ${bodyClassName}">
198
+ ${children}
199
+ </div>
200
+ </div>
201
+ `;
202
+ };
203
+
204
+ const LoadingSpinner = () => {
205
+ return `
206
+ <div class="flex items-center justify-center h-64">
207
+ <i class="fas fa-circle-notch fa-spin text-4xl text-indigo-500 loading-spinner"></i>
208
+ </div>
209
+ `;
210
+ };
211
+
212
+ // Componentes principais
213
+ const App = () => {
214
+ const [darkMode, setDarkMode] = useState(true);
215
+ const [activeSection, setActiveSection] = useState('dashboard');
216
+ const [isLoading, setIsLoading] = useState(true);
217
+ const [dashboardData, setDashboardData] = useState(null);
218
+ const [news, setNews] = useState([]);
219
+ const [alerts, setAlerts] = useState([]);
220
+
221
+ const toggleDarkMode = () => {
222
+ setDarkMode(prev => {
223
+ const newMode = !prev;
224
+ document.body.classList.toggle('dark');
225
+ document.body.classList.toggle('light');
226
+ return newMode;
227
+ });
228
+ };
229
+
230
+ const fetchData = async () => {
231
+ setIsLoading(true);
232
+ try {
233
+ const [dashboard, newsData, alertsData] = await Promise.all([
234
+ ApiService.getDashboardData(),
235
+ ApiService.getNews(),
236
+ ApiService.getAlerts()
237
+ ]);
238
+
239
+ setDashboardData(dashboard);
240
+ setNews(newsData);
241
+ setAlerts(alertsData);
242
+ } catch (error) {
243
+ console.error('Erro ao carregar dados:', error);
244
+ } finally {
245
+ setIsLoading(false);
246
+ }
247
+ };
248
+
249
+ useEffect(() => {
250
+ fetchData();
251
+ }, []);
252
+
253
+ const renderSection = () => {
254
+ if (isLoading) return LoadingSpinner();
255
+
256
+ switch (activeSection) {
257
+ case 'dashboard':
258
+ return DashboardSection({ dashboardData, news, alerts });
259
+ case 'news':
260
+ return NewsSection({ news });
261
+ case 'alerts':
262
+ return AlertsSection({ alerts });
263
+ case 'reports':
264
+ return ReportsSection();
265
+ default:
266
+ return DashboardSection({ dashboardData, news, alerts });
267
+ }
268
+ };
269
+
270
+ return `
271
+ <div class="flex h-screen overflow-hidden">
272
+ <!-- Sidebar -->
273
+ ${Sidebar({ activeSection, setActiveSection })}
274
+
275
+ <!-- Main Content -->
276
+ <div class="flex-1 overflow-auto">
277
+ <!-- Header -->
278
+ ${Header({
279
+ activeSection,
280
+ darkMode,
281
+ toggleDarkMode,
282
+ isLoading
283
+ })}
284
+
285
+ <!-- Main Content -->
286
+ <main class="p-4 md:p-6">
287
+ ${renderSection()}
288
+ </main>
289
+ </div>
290
+ </div>
291
+ `;
292
+ };
293
+
294
+ const Sidebar = ({ activeSection, setActiveSection }) => {
295
+ const sections = [
296
+ { id: 'dashboard', icon: 'fa-tachometer-alt', label: 'Dashboard' },
297
+ { id: 'news', icon: 'fa-newspaper', label: 'Notícias' },
298
+ { id: 'alerts', icon: 'fa-bell', label: 'Alertas' },
299
+ { id: 'reports', icon: 'fa-flag', label: 'Denúncias' }
300
+ ];
301
+
302
+ return `
303
+ <div class="sidebar w-16 md:w-64 flex-shrink-0 flex flex-col">
304
+ <div class="p-4 border-b border-gray-700 flex items-center justify-center md:justify-between">
305
+ <h1 class="text-xl font-bold text-white flex items-center">
306
+ <i class="fas fa-search text-indigo-500 mr-0 md:mr-2"></i>
307
+ <span class="hidden md:inline">DeekSeek</span>
308
+ </h1>
309
+ </div>
310
+
311
+ <div class="flex-1 overflow-y-auto">
312
+ <nav class="p-2 md:p-4 sidebar-nav">
313
+ <ul class="space-y-1 md:space-y-2">
314
+ ${sections.map(section => `
315
+ <li key="${section.id}" class="mb-0 md:mb-2">
316
+ ${Button({
317
+ onClick: `(${setActiveSection})('${section.id}')`,
318
+ variant: activeSection === section.id ? 'primary' : 'ghost',
319
+ className: `w-full text-left ${activeSection === section.id ? 'bg-indigo-500/20 text-indigo-400' : 'hover:bg-gray-700'}`,
320
+ icon: section.icon,
321
+ children: `<span class="hidden md:inline">${section.label}</span>`
322
+ })}
323
+ </li>
324
+ `).join('')}
325
+ </ul>
326
+ </nav>
327
+ </div>
328
+
329
+ <div class="p-4 border-t border-gray-700 user-profile">
330
+ <div class="flex items-center justify-center md:justify-between">
331
+ <div class="flex items-center">
332
+ <div class="w-10 h-10 rounded-full bg-indigo-500 flex items-center justify-center">
333
+ <i class="fas fa-user text-white"></i>
334
+ </div>
335
+ <div class="ml-3 hidden md:block">
336
+ <p class="text-sm font-medium">Usuário</p>
337
+ <p class="text-xs text-gray-400">Admin</p>
338
+ </div>
339
+ </div>
340
+ </div>
341
+ </div>
342
+ </div>
343
+ `;
344
+ };
345
+
346
+ const Header = ({ activeSection, darkMode, toggleDarkMode, isLoading }) => {
347
+ const sectionTitles = {
348
+ dashboard: 'Dashboard',
349
+ news: 'Gerenciamento de Notícias',
350
+ alerts: 'Monitoramento de Alertas',
351
+ reports: 'Registro de Denúncias'
352
+ };
353
+
354
+ return `
355
+ <header class="bg-gray-800 border-b border-gray-700 p-4 flex flex-col md:flex-row justify-between items-start md:items-center space-y-3 md:space-y-0">
356
+ <h2 class="text-xl font-semibold">${sectionTitles[activeSection]}</h2>
357
+
358
+ <div class="flex items-center space-x-2 md:space-x-4 w-full md:w-auto">
359
+ <div class="relative flex-1 md:flex-none">
360
+ <i class="fas fa-search absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400"></i>
361
+ <input
362
+ type="text"
363
+ placeholder="Pesquisar..."
364
+ class="bg-gray-700 border border-gray-600 rounded-lg pl-10 pr-4 py-2 focus:outline-none focus:ring-2 focus:ring-indigo-500 w-full md:w-64"
365
+ ${isLoading ? 'disabled' : ''}
366
+ />
367
+ </div>
368
+
369
+ ${Button({
370
+ icon: darkMode ? 'fa-sun' : 'fa-moon',
371
+ variant: 'ghost',
372
+ onClick: `(${toggleDarkMode})()`,
373
+ size: 'sm'
374
+ })}
375
+ </div>
376
+ </header>
377
+ `;
378
+ };
379
+
380
+ // Seções
381
+ const DashboardSection = ({ dashboardData, news, alerts }) => {
382
+ if (!dashboardData) return LoadingSpinner();
383
+
384
+ return `
385
+ <div class="space-y-6">
386
+ <!-- Quick Stats -->
387
+ <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
388
+ ${Card({
389
+ className: 'relative',
390
+ children: `
391
+ <div class="flex justify-between items-start">
392
+ <div>
393
+ <p class="text-gray-400">Notícias</p>
394
+ <h3 class="text-2xl font-bold mt-1">${news.length}</h3>
395
+ </div>
396
+ <div class="bg-blue-500/10 p-3 rounded-full">
397
+ <i class="fas fa-newspaper text-blue-500"></i>
398
+ </div>
399
+ </div>
400
+ `
401
+ })}
402
+
403
+ ${Card({
404
+ className: 'relative',
405
+ children: `
406
+ <div class="flex justify-between items-start">
407
+ <div>
408
+ <p class="text-gray-400">Alertas</p>
409
+ <h3 class="text-2xl font-bold mt-1">${alerts.length}</h3>
410
+ </div>
411
+ <div class="bg-red-500/10 p-3 rounded-full">
412
+ <i class="fas fa-bell text-red-500"></i>
413
+ </div>
414
+ </div>
415
+ `
416
+ })}
417
+
418
+ ${Card({
419
+ className: 'relative',
420
+ children: `
421
+ <div class="flex justify-between items-start">
422
+ <div>
423
+ <p class="text-gray-400">Última Atualização</p>
424
+ <h3 class="text-2xl font-bold mt-1">${new Date(dashboardData.lastUpdated).toLocaleTimeString()}</h3>
425
+ </div>
426
+ <div class="bg-green-500/10 p-3 rounded-full">
427
+ <i class="fas fa-clock text-green-500"></i>
428
+ </div>
429
+ </div>
430
+ `
431
+ })}
432
+
433
+ ${Card({
434
+ className: 'relative',
435
+ children: `
436
+ <div class="flex justify-between items-start">
437
+ <div>
438
+ <p class="text-gray-400">Status do Sistema</p>
439
+ <h3 class="text-2xl font-bold mt-1">${dashboardData.systemStatus}</h3>
440
+ </div>
441
+ <div class="bg-yellow-500/10 p-3 rounded-full">
442
+ <i class="fas fa-server text-yellow-500"></i>
443
+ </div>
444
+ </div>
445
+ `
446
+ })}
447
+ </div>
448
+
449
+ <!-- Recent Activity -->
450
+ ${Card({
451
+ title: 'Atividade Recente',
452
+ children: `
453
+ <div class="space-y-4">
454
+ ${alerts.slice(0, 5).map(alert => `
455
+ <div class="flex items-start">
456
+ <div class="p-2 rounded-full mr-3 bg-red-500/10 text-red-500">
457
+ <i class="fas fa-exclamation-triangle"></i>
458
+ </div>
459
+ <div>
460
+ <p class="text-sm">${alert.message}</p>
461
+ <p class="text-xs text-gray-400">${new Date(alert.date).toLocaleString()}</p>
462
+ </div>
463
+ </div>
464
+ `).join('')}
465
+ </div>
466
+ `
467
+ })}
468
+ </div>
469
+ `;
470
+ };
471
+
472
+ const NewsSection = ({ news }) => {
473
+ const [selectedNews, setSelectedNews] = useState(null);
474
+
475
+ return `
476
+ <div class="space-y-6">
477
+ <div class="flex justify-between items-center">
478
+ <h3 class="text-lg font-semibold">Gerenciamento de Notícias</h3>
479
+ ${Button({
480
+ onClick: "alert('Funcionalidade de adicionar notícia será implementada')",
481
+ variant: 'primary',
482
+ icon: 'fa-plus',
483
+ children: 'Adicionar Notícia'
484
+ })}
485
+ </div>
486
+
487
+ <div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
488
+ <!-- News List -->
489
+ <div class="lg:col-span-1">
490
+ ${Card({
491
+ title: 'Lista de Notícias',
492
+ children: `
493
+ <div class="space-y-3">
494
+ ${news.map(item => `
495
+ <div
496
+ onclick="(${setSelectedNews})(${JSON.stringify(item)})"
497
+ class="p-3 rounded-lg cursor-pointer transition-all ${
498
+ selectedNews?.id === item.id ? 'bg-indigo-500/10 border border-indigo-500/30' : 'hover:bg-gray-700'
499
+ }"
500
+ >
501
+ <div class="flex justify-between items-center">
502
+ <h4 class="font-medium truncate">${item.title}</h4>
503
+ <span class="px-2 py-1 text-xs rounded-full bg-green-500/20 text-green-400">
504
+ ${item.status}
505
+ </span>
506
+ </div>
507
+ <p class="text-sm text-gray-400 truncate">${item.source}</p>
508
+ <div class="flex justify-between mt-2 text-xs">
509
+ <span class="text-gray-400">Publicado em: ${new Date(item.publishedDate).toLocaleDateString()}</span>
510
+ </div>
511
+ </div>
512
+ `).join('')}
513
+ </div>
514
+ `
515
+ })}
516
+ </div>
517
+
518
+ <!-- News Details -->
519
+ <div class="lg:col-span-2">
520
+ ${selectedNews ? `
521
+ ${Card({
522
+ children: `
523
+ <div class="flex flex-col md:flex-row md:justify-between md:items-center mb-4 space-y-3 md:space-y-0">
524
+ <h3 class="text-xl font-semibold">${selectedNews.title}</h3>
525
+ <div class="flex space-x-2">
526
+ ${Button({
527
+ variant: 'primary',
528
+ size: 'sm',
529
+ icon: 'fa-edit',
530
+ children: 'Editar'
531
+ })}
532
+ ${Button({
533
+ variant: 'danger',
534
+ size: 'sm',
535
+ icon: 'fa-trash',
536
+ children: 'Excluir'
537
+ })}
538
+ </div>
539
+ </div>
540
+
541
+ <div class="grid grid-cols-1 sm:grid-cols-2 gap-4 mb-6">
542
+ ${Card({
543
+ children: `
544
+ <p class="text-gray-400 text-sm">Fonte</p>
545
+ <p class="font-medium">${selectedNews.source}</p>
546
+ `
547
+ })}
548
+ ${Card({
549
+ children: `
550
+ <p class="text-gray-400 text-sm">Status</p>
551
+ <span class="px-2 py-1 text-xs rounded-full bg-green-500/20 text-green-400">
552
+ ${selectedNews.status}
553
+ </span>
554
+ `
555
+ })}
556
+ ${Card({
557
+ children: `
558
+ <p class="text-gray-400 text-sm">Data de Publicação</p>
559
+ <p class="font-medium">${new Date(selectedNews.publishedDate).toLocaleString()}</p>
560
+ `
561
+ })}
562
+ ${Card({
563
+ children: `
564
+ <p class="text-gray-400 text-sm">Autor</p>
565
+ <p class="font-medium">${selectedNews.author}</p>
566
+ `
567
+ })}
568
+ </div>
569
+
570
+ <div>
571
+ <h4 class="font-medium mb-3">Conteúdo</h4>
572
+ <div class="bg-gray-800 border border-gray-700 rounded-lg p-4">
573
+ <p class="text-gray-300">${selectedNews.content}</p>
574
+ </div>
575
+ </div>
576
+ `
577
+ })}
578
+ ` : `
579
+ ${Card({
580
+ className: 'flex flex-col items-center justify-center h-64',
581
+ children: `
582
+ <i class="fas fa-newspaper text-4xl text-gray-500 mb-4"></i>
583
+ <p class="text-gray-400">Selecione uma notícia para visualizar os detalhes</p>
584
+ `
585
+ })}
586
+ `}
587
+ </div>
588
+ </div>
589
+ </div>
590
+ `;
591
+ };
592
+
593
+ const AlertsSection = ({ alerts }) => {
594
+ const [selectedAlert, setSelectedAlert] = useState(null);
595
+
596
+ return `
597
+ <div class="space-y-6">
598
+ <div class="flex justify-between items-center">
599
+ <h3 class="text-lg font-semibold">Monitoramento de Alertas</h3>
600
+ ${Button({
601
+ onClick: "alert('Funcionalidade de configuração de alertas será implementada')",
602
+ variant: 'primary',
603
+ icon: 'fa-cog',
604
+ children: 'Configurar'
605
+ })}
606
+ </div>
607
+
608
+ <div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
609
+ <!-- Alerts List -->
610
+ <div class="lg:col-span-1">
611
+ ${Card({
612
+ title: 'Lista de Alertas',
613
+ children: `
614
+ <div class="space-y-3">
615
+ ${alerts.map(alert => `
616
+ <div
617
+ onclick="(${setSelectedAlert})(${JSON.stringify(alert)})"
618
+ class="p-3 rounded-lg cursor-pointer transition-all ${
619
+ selectedAlert?.id === alert.id ? 'bg-indigo-500/10 border border-indigo-500/30' : 'hover:bg-gray-700'
620
+ }"
621
+ >
622
+ <div class="flex justify-between items-center">
623
+ <h4 class="font-medium truncate">${alert.title}</h4>
624
+ <span class="px-2 py-1 text-xs rounded-full bg-red-500/20 text-red-400">
625
+ ${alert.severity}
626
+ </span>
627
+ </div>
628
+ <p class="text-sm text-gray-400 truncate">${alert.source}</p>
629
+ <div class="flex justify-between mt-2 text-xs">
630
+ <span class="text-gray-400">Detectado em: ${new Date(alert.detectedAt).toLocaleTimeString()}</span>
631
+ </div>
632
+ </div>
633
+ `).join('')}
634
+ </div>
635
+ `
636
+ })}
637
+ </div>
638
+
639
+ <!-- Alert Details -->
640
+ <div class="lg:col-span-2">
641
+ ${selectedAlert ? `
642
+ ${Card({
643
+ children: `
644
+ <div class="flex flex-col md:flex-row md:justify-between md:items-center mb-4 space-y-3 md:space-y-0">
645
+ <h3 class="text-xl font-semibold">${selectedAlert.title}</h3>
646
+ <div class="flex space-x-2">
647
+ ${Button({
648
+ variant: 'primary',
649
+ size: 'sm',
650
+ icon: 'fa-check',
651
+ children: 'Resolver'
652
+ })}
653
+ ${Button({
654
+ variant: 'danger',
655
+ size: 'sm',
656
+ icon: 'fa-trash',
657
+ children: 'Ignorar'
658
+ })}
659
+ </div>
660
+ </div>
661
+
662
+ <div class="grid grid-cols-1 sm:grid-cols-2 gap-4 mb-6">
663
+ ${Card({
664
+ children: `
665
+ <p class="text-gray-400 text-sm">Fonte</p>
666
+ <p class="font-medium">${selectedAlert.source}</p>
667
+ `
668
+ })}
669
+ ${Card({
670
+ children: `
671
+ <p class="text-gray-400 text-sm">Gravidade</p>
672
+ <span class="px-2 py-1 text-xs rounded-full bg-red-500/20 text-red-400">
673
+ ${selectedAlert.severity}
674
+ </span>
675
+ `
676
+ })}
677
+ ${Card({
678
+ children: `
679
+ <p class="text-gray-400 text-sm">Detectado em</p>
680
+ <p class="font-medium">${new Date(selectedAlert.detectedAt).toLocaleString()}</p>
681
+ `
682
+ })}
683
+ ${Card({
684
+ children: `
685
+ <p class="text-gray-400 text-sm">Status</p>
686
+ <span class="px-2 py-1 text-xs rounded-full bg-yellow-500/20 text-yellow-400">
687
+ ${selectedAlert.status}
688
+ </span>
689
+ `
690
+ })}
691
+ </div>
692
+
693
+ <div>
694
+ <h4 class="font-medium mb-3">Detalhes</h4>
695
+ <div class="bg-gray-800 border border-gray-700 rounded-lg p-4">
696
+ <p class="text-gray-300">${selectedAlert.details}</p>
697
+ </div>
698
+ </div>
699
+ `
700
+ })}
701
+ ` : `
702
+ ${Card({
703
+ className: 'flex flex-col items-center justify-center h-64',
704
+ children: `
705
+ <i class="fas fa-bell text-4xl text-gray-500 mb-4"></i>
706
+ <p class="text-gray-400">Selecione um alerta para visualizar os detalhes</p>
707
+ `
708
+ })}
709
+ `}
710
+ </div>
711
+ </div>
712
+ </div>
713
+ `;
714
+ };
715
+
716
+ const ReportsSection = () => {
717
+ const [reportData, setReportData] = useState({
718
+ title: '',
719
+ description: '',
720
+ category: 'spam',
721
+ urgency: 'medium'
722
+ });
723
+ const [isSubmitting, setIsSubmitting] = useState(false);
724
+
725
+ const handleSubmit = async (e) => {
726
+ e.preventDefault();
727
+ setIsSubmitting(true);
728
+
729
+ try {
730
+ await ApiService.postReport(reportData);
731
+ alert('Denúncia enviada com sucesso!');
732
+ setReportData({
733
+ title: '',
734
+ description: '',
735
+ category: 'spam',
736
+ urgency: 'medium'
737
+ });
738
+ } catch (error) {
739
+ alert('Erro ao enviar denúncia. Por favor, tente novamente.');
740
+ } finally {
741
+ setIsSubmitting(false);
742
+ }
743
+ };
744
+
745
+ return `
746
+ <div class="space-y-6">
747
+ <div class="flex justify-between items-center">
748
+ <h3 class="text-lg font-semibold">Registro de Denúncias</h3>
749
+ </div>
750
+
751
+ ${Card({
752
+ children: `
753
+ <form onsubmit="event.preventDefault(); (${handleSubmit})(event);">
754
+ <div class="space-y-4">
755
+ <div>
756
+ <label class="block text-sm font-medium text-gray-400 mb-1">Título</label>
757
+ <input
758
+ type="text"
759
+ value="${reportData.title}"
760
+ onchange="(${setReportData})({...${JSON.stringify(reportData)}, title: event.target.value})"
761
+ placeholder="Resumo da denúncia"
762
+ class="w-full bg-gray-700 border border-gray-600 rounded-lg px-4 py-2 focus:outline-none focus:ring-2 focus:ring-indigo-500"
763
+ required
764
+ />
765
+ </div>
766
+
767
+ <div>
768
+ <label class="block text-sm font-medium text-gray-400 mb-1">Descrição</label>
769
+ <textarea
770
+ value="${reportData.description}"
771
+ onchange="(${setReportData})({...${JSON.stringify(reportData)}, description: event.target.value})"
772
+ placeholder="Descreva detalhadamente o problema encontrado"
773
+ class="w-full bg-gray-700 border border-gray-600 rounded-lg px-4 py-2 focus:outline-none focus:ring-2 focus:ring-indigo-500 h-32"
774
+ required
775
+ ></textarea>
776
+ </div>
777
+
778
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
779
+ <div>
780
+ <label class="block text-sm font-medium text-gray-400 mb-1">Categoria</label>
781
+ <select
782
+ value="${reportData.category}"
783
+ onchange="(${setReportData})({...${JSON.stringify(reportData)}, category: event.target.value})"
784
+ class="w-full bg-gray-700 border border-gray-600 rounded-lg px-4 py-2 focus:outline-none focus:ring-2 focus:ring-indigo-500"
785
+ >
786
+ <option value="spam">Spam</option>
787
+ <option value="fake_news">Fake News</option>
788
+ <option value="inappropriate">Conteúdo Inapropriado</option>
789
+ <option value="other">Outro</option>
790
+ </select>
791
+ </div>
792
+
793
+ <div>
794
+ <label class="block text-sm font-medium text-gray-400 mb-1">Urgência</label>
795
+ <select
796
+ value="${reportData.urgency}"
797
+ onchange="(${setReportData})({...${JSON.stringify(reportData)}, urgency: event.target.value})"
798
+ class="w-full bg-gray-700 border border-gray-600 rounded-lg px-4 py-2 focus:outline-none focus:ring-2 focus:ring-indigo-500"
799
+ >
800
+ <option value="low">Baixa</option>
801
+ <option value="medium">Média</option>
802
+ <option value="high">Alta</option>
803
+ </select>
804
+ </div>
805
+ </div>
806
+
807
+ <div class="flex justify-end pt-4">
808
+ ${Button({
809
+ type: 'submit',
810
+ variant: 'primary',
811
+ disabled: isSubmitting,
812
+ children: isSubmitting ? `
813
+ <i class="fas fa-circle-notch fa-spin mr-2 loading-spinner"></i>
814
+ Enviando...
815
+ ` : 'Enviar Denúncia'
816
+ })}
817
+ </div>
818
+ </div>
819
+ </form>
820
+ `
821
+ })}
822
+ </div>
823
+ `;
824
+ };
825
+
826
+ // Funções auxiliares
827
+ function useState(initialValue) {
828
+ let state = initialValue;
829
+ const listeners = [];
830
+
831
+ function setState(newValue) {
832
+ state = typeof newValue === 'function' ? newValue(state) : newValue;
833
+ listeners.forEach(listener => listener(state));
834
+ }
835
+
836
+ function useEffect(callback, deps) {
837
+ callback();
838
+ }
839
+
840
+ function render() {
841
+ document.getElementById('root').innerHTML = App();
842
+ }
843
+
844
+ listeners.push(render);
845
+
846
+ return [state, setState, useEffect];
847
+ }
848
+
849
+ // Inicialização
850
+ const [darkMode, setDarkMode, useEffect] = useState(true);
851
+ document.getElementById('root').innerHTML = App();
852
+ </script>
853
+
854
+ <!-- SERVER.JS - BACKEND COMPLETO -->
855
+ <script>
856
+ // Este é o código do servidor Node.js que você deve salvar em um arquivo server.js separado
857
+ // e executar com: node server.js
858
+
859
+ const serverCode = `
860
+ const express = require('express');
861
+ const cors = require('cors');
862
+ const bodyParser = require('body-parser');
863
+
864
+ const app = express();
865
+ const PORT = 3000;
866
+
867
+ // Middleware
868
+ app.use(cors());
869
+ app.use(bodyParser.json());
870
+
871
+ // Dados mockados
872
+ const news = [
873
+ {
874
+ id: 1,
875
+ title: "Nova atualização do sistema",
876
+ source: "Portal Tech",
877
+ status: "Ativo",
878
+ publishedDate: "2023-05-15T10:30:00",
879
+ author: "João Silva",
880
+ content: "A nova atualização do sistema traz melhorias significativas na performance e segurança. Todos os usuários devem atualizar assim que possível."
881
+ },
882
+ {
883
+ id: 2,
884
+ title: "Alerta de segurança",
885
+ source: "Segurança Digital",
886
+ status: "Crítico",
887
+ publishedDate: "2023-05-10T08:15:00",
888
+ author: "Maria Souza",
889
+ content: "Foi identificada uma vulnerabilidade crítica no sistema. Recomenda-se a aplicação imediata do patch de segurança."
890
+ },
891
+ {
892
+ id: 3,
893
+ title: "Manutenção programada",
894
+ source: "TI Corporativa",
895
+ status: "Aviso",
896
+ publishedDate: "2023-05-05T14:00:00",
897
+ author: "Carlos Oliveira",
898
+ content: "Será realizada uma manutenção programada no próximo sábado entre 00:00 e 04:00. O sistema ficará indisponível durante este período."
899
+ },
900
+ {
901
+ id: 4,
902
+ title: "Novo recurso disponível",
903
+ source: "Desenvolvimento",
904
+ status: "Ativo",
905
+ publishedDate: "2023-04-28T16:45:00",
906
+ author: "Ana Santos",
907
+ content: "O novo módulo de relatórios está disponível para todos os usuários. Consulte a documentação para mais detalhes."
908
+ },
909
+ {
910
+ id: 5,
911
+ title: "Treinamento de usuários",
912
+ source: "RH Corporativo",
913
+ status: "Informação",
914
+ publishedDate: "2023-04-20T09:00:00",
915
+ author: "Pedro Rocha",
916
+ content: "Serão realizados treinamentos sobre as novas funcionalidades do sistema nos dias 25 e 26 deste mês."
917
+ }
918
+ ];
919
+
920
+ const alerts = [
921
+ {
922
+ id: 1,
923
+ title: "Tentativa de acesso não autorizado",
924
+ source: "Sistema de Segurança",
925
+ severity: "Alta",
926
+ detectedAt: "2023-05-16T03:25:00",
927
+ status: "Não resolvido",
928
+ details: "Múltiplas tentativas de login falhas detectadas na conta de administrador. Possível ataque de força bruta."
929
+ },
930
+ {
931
+ id: 2,
932
+ title: "Alta carga no servidor",
933
+ source: "Monitoramento",
934
+ severity: "Média",
935
+ detectedAt: "2023-05-15T14:30:00",
936
+ status: "Em análise",
937
+ details: "O servidor principal está operando com 95% de utilização de CPU. Recomenda-se investigação imediata."
938
+ },
939
+ {
940
+ id: 3,
941
+ title: "Backup falhou",
942
+ source: "Sistema de Backup",
943
+ severity: "Crítica",
944
+ detectedAt: "2023-05-15T02:00:00",
945
+ status: "Não resolvido",
946
+ details: "O backup automático noturno falhou devido a espaço insuficiente em disco. Ação necessária."
947
+ },
948
+ {
949
+ id: 4,
950
+ title: "Atualização pendente",
951
+ source: "Gerenciador de Pacotes",
952
+ severity: "Baixa",
953
+ detectedAt: "2023-05-14T09:15:00",
954
+ status: "Pendente",
955
+ details: "Existem 5 atualizações de segurança pendentes para aplicação no servidor."
956
+ },
957
+ {
958
+ id: 5,
959
+ title: "Tráfego suspeito",
960
+ source: "Firewall",
961
+ severity: "Média",
962
+ detectedAt: "2023-05-13T18:45:00",
963
+ status: "Resolvido",
964
+ details: "Foi detectado tráfego incomum vindo do IP 192.168.1.100. O firewall bloqueou automaticamente."
965
+ }
966
+ ];
967
+
968
+ // Rotas da API
969
+ app.get('/api/news', (req, res) => {
970
+ res.json(news);
971
+ });
972
+
973
+ app.get('/api/alerts', (req, res) => {
974
+ res.json(alerts);
975
+ });
976
+
977
+ app.get('/api/dashboard', (req, res) => {
978
+ res.json({
979
+ lastUpdated: new Date().toISOString(),
980
+ systemStatus: "Operacional",
981
+ stats: {
982
+ newsCount: news.length,
983
+ alertsCount: alerts.length,
984
+ resolvedAlerts: alerts.filter(a => a.status === "Resolvido").length
985
+ }
986
+ });
987
+ });
988
+
989
+ app.post('/api/denuncias', (req, res) => {
990
+ const { title, description, category, urgency } = req.body;
991
+
992
+ if (!title || !description) {
993
+ return res.status(400).json({ error: "Título e descrição são obrigatórios" });
994
+ }
995
+
996
+ // Simula processamento
997
+ setTimeout(() => {
998
+ res.json({
999
+ success: true,
1000
+ message: "Denúncia registrada com sucesso",
1001
+ data: {
1002
+ id: Math.floor(Math.random() * 1000),
1003
+ title,
1004
+ description,
1005
+ category,
1006
+ urgency,
1007
+ status: "Recebido",
1008
+ createdAt: new Date().toISOString()
1009
+ }
1010
+ });
1011
+ }, 1000);
1012
+ });
1013
+
1014
+ // Rota de teste
1015
+ app.get('/', (req, res) => {
1016
+ res.send('API DeekSeek está rodando!');
1017
+ });
1018
+
1019
+ // Inicia o servidor
1020
+ app.listen(PORT, () => {
1021
+ console.log(\`Servidor rodando em http://localhost:\${PORT}\`);
1022
+ });
1023
+ `;
1024
+
1025
+ // Instruções para executar o servidor
1026
+ const instructions = `
1027
+ // INSTRUÇÕES PARA EXECUTAR O BACKEND:
1028
+
1029
+ 1. Crie um arquivo chamado server.js e cole todo o código acima (dentro das crases)
1030
+ 2. Certifique-se de ter o Node.js instalado (https://nodejs.org/)
1031
+ 3. No terminal, instale as dependências necessárias:
1032
+ npm install express cors body-parser
1033
+ 4. Inicie o servidor:
1034
+ node server.js
1035
+ 5. O servidor estará disponível em http://localhost:3000
1036
+ 6. As rotas da API serão:
1037
+ - GET /api/news - Lista de notícias
1038
+ - GET /api/alerts - Lista de alertas
1039
+ - GET /api/dashboard - Dados do dashboard
1040
+ - POST /api/denuncias - Enviar denúncias
1041
+ `;
1042
+
1043
+ console.log('Código do servidor disponível para cópia. Veja as instruções no console.');
1044
+ console.log(instructions);
1045
+ </script>
1046
+ <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=dandydow/backend-final-full" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
1047
+ </html>
prompts.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ Mano, preciso que você finalize de verdade o back-end. Não é exemplo, é funcional. Quero: Um servidor Node.js + Express. Com rotas reais para /news, /alerts, /dashboard e /denuncias. Cada rota deve responder com dados falsos (mockados) em formato JSON pra conectar com o front. Backend rodando local (porta 3000) e documentado. Pode ser em um arquivo server.js. O objetivo é: se eu abrir o front, ele realmente consiga buscar os dados no back que você criou. Sem enrolar, é pra fazer rodar.