create-fluxstack 1.8.1 → 1.8.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. package/.env.example +19 -0
  2. package/README.md +6 -3
  3. package/app/client/SIMPLIFICATION.md +140 -0
  4. package/app/client/frontend-only.ts +1 -1
  5. package/app/client/src/App.tsx +148 -283
  6. package/app/client/src/index.css +5 -20
  7. package/app/client/src/lib/eden-api.ts +53 -220
  8. package/app/client/src/main.tsx +2 -3
  9. package/app/server/controllers/users.controller.ts +57 -31
  10. package/app/server/index.ts +5 -2
  11. package/app/server/live/register-components.ts +18 -7
  12. package/app/server/routes/env-test.ts +53 -2
  13. package/app/server/routes/index.ts +1 -8
  14. package/app/server/routes/users.routes.ts +192 -91
  15. package/config/fluxstack.config.ts +2 -2
  16. package/config/plugins.config.ts +22 -1
  17. package/core/build/flux-plugins-generator.ts +5 -5
  18. package/core/build/live-components-generator.ts +15 -12
  19. package/core/cli/command-registry.ts +4 -14
  20. package/core/cli/commands/plugin-deps.ts +8 -8
  21. package/core/cli/generators/component.ts +3 -3
  22. package/core/cli/generators/controller.ts +4 -4
  23. package/core/cli/generators/index.ts +8 -8
  24. package/core/cli/generators/interactive.ts +4 -4
  25. package/core/cli/generators/plugin.ts +3 -3
  26. package/core/cli/generators/prompts.ts +1 -1
  27. package/core/cli/generators/route.ts +27 -11
  28. package/core/cli/generators/service.ts +5 -5
  29. package/core/cli/generators/template-engine.ts +1 -1
  30. package/core/cli/generators/types.ts +1 -1
  31. package/core/cli/index.ts +158 -193
  32. package/core/cli/plugin-discovery.ts +3 -3
  33. package/core/client/hooks/index.ts +2 -2
  34. package/core/client/hooks/state-validator.ts +1 -1
  35. package/core/client/hooks/useAuth.ts +1 -1
  36. package/core/client/hooks/useChunkedUpload.ts +1 -1
  37. package/core/client/hooks/useHybridLiveComponent.ts +1 -1
  38. package/core/client/hooks/useWebSocket.ts +1 -1
  39. package/core/config/env.ts +1 -1
  40. package/core/config/runtime-config.ts +5 -5
  41. package/core/config/schema.ts +9 -0
  42. package/core/framework/server.ts +30 -15
  43. package/core/framework/types.ts +2 -2
  44. package/core/live/ComponentRegistry.ts +1 -1
  45. package/core/plugins/built-in/live-components/commands/create-live-component.ts +1 -1
  46. package/core/plugins/built-in/live-components/index.ts +1 -1
  47. package/core/plugins/built-in/monitoring/index.ts +65 -161
  48. package/core/plugins/built-in/static/index.ts +18 -47
  49. package/core/plugins/built-in/swagger/index.ts +301 -231
  50. package/core/plugins/built-in/vite/index.ts +74 -109
  51. package/core/plugins/config.ts +2 -2
  52. package/core/plugins/dependency-manager.ts +2 -2
  53. package/core/plugins/discovery.ts +1 -1
  54. package/core/plugins/executor.ts +2 -2
  55. package/core/plugins/manager.ts +19 -4
  56. package/core/plugins/module-resolver.ts +1 -1
  57. package/core/plugins/registry.ts +3 -3
  58. package/core/plugins/types.ts +147 -5
  59. package/core/server/framework.ts +2 -2
  60. package/core/server/live/ComponentRegistry.ts +9 -26
  61. package/core/server/live/FileUploadManager.ts +1 -1
  62. package/core/server/live/auto-generated-components.ts +26 -0
  63. package/core/server/live/websocket-plugin.ts +211 -19
  64. package/core/server/middleware/errorHandling.ts +1 -1
  65. package/core/server/middleware/index.ts +4 -4
  66. package/core/server/plugins/database.ts +1 -2
  67. package/core/server/plugins/static-files-plugin.ts +259 -231
  68. package/core/server/plugins/swagger.ts +1 -1
  69. package/core/server/services/BaseService.ts +1 -1
  70. package/core/server/services/ServiceContainer.ts +1 -1
  71. package/core/server/services/index.ts +4 -4
  72. package/core/server/standalone.ts +16 -1
  73. package/core/testing/index.ts +1 -1
  74. package/core/testing/setup.ts +1 -1
  75. package/core/utils/logger/startup-banner.ts +7 -33
  76. package/core/utils/version.ts +6 -6
  77. package/create-fluxstack.ts +68 -25
  78. package/package.json +2 -2
  79. package/plugins/crypto-auth/index.ts +52 -47
  80. package/plugins/crypto-auth/server/AuthMiddleware.ts +1 -1
  81. package/plugins/crypto-auth/server/middlewares/helpers.ts +16 -1
  82. package/vitest.config.ts +11 -2
  83. package/app/client/src/App.css +0 -883
  84. package/app/client/src/components/ErrorBoundary.tsx +0 -107
  85. package/app/client/src/components/ErrorDisplay.css +0 -365
  86. package/app/client/src/components/ErrorDisplay.tsx +0 -258
  87. package/app/client/src/components/FluxStackConfig.tsx +0 -1321
  88. package/app/client/src/components/HybridLiveCounter.tsx +0 -140
  89. package/app/client/src/components/LiveClock.tsx +0 -286
  90. package/app/client/src/components/MainLayout.tsx +0 -388
  91. package/app/client/src/components/SidebarNavigation.tsx +0 -391
  92. package/app/client/src/components/StateDemo.tsx +0 -178
  93. package/app/client/src/components/SystemMonitor.tsx +0 -1044
  94. package/app/client/src/components/UserProfile.tsx +0 -809
  95. package/app/client/src/hooks/useAuth.ts +0 -39
  96. package/app/client/src/hooks/useNotifications.ts +0 -56
  97. package/app/client/src/lib/errors.ts +0 -340
  98. package/app/client/src/lib/hooks/useErrorHandler.ts +0 -258
  99. package/app/client/src/lib/index.ts +0 -45
  100. package/app/client/src/pages/ApiDocs.tsx +0 -182
  101. package/app/client/src/pages/CryptoAuthPage.tsx +0 -394
  102. package/app/client/src/pages/Demo.tsx +0 -174
  103. package/app/client/src/pages/HybridLive.tsx +0 -263
  104. package/app/client/src/pages/Overview.tsx +0 -155
  105. package/app/client/src/store/README.md +0 -43
  106. package/app/client/src/store/index.ts +0 -16
  107. package/app/client/src/store/slices/uiSlice.ts +0 -151
  108. package/app/client/src/store/slices/userSlice.ts +0 -161
  109. package/app/client/src/test/README.md +0 -257
  110. package/app/client/src/test/setup.ts +0 -70
  111. package/app/client/src/test/types.ts +0 -12
  112. package/app/server/live/CounterComponent.ts +0 -191
  113. package/app/server/live/FluxStackConfig.ts +0 -534
  114. package/app/server/live/SidebarNavigation.ts +0 -157
  115. package/app/server/live/SystemMonitor.ts +0 -595
  116. package/app/server/live/SystemMonitorIntegration.ts +0 -151
  117. package/app/server/live/UserProfileComponent.ts +0 -141
  118. package/app/server/middleware/auth.ts +0 -136
  119. package/app/server/middleware/errorHandling.ts +0 -252
  120. package/app/server/middleware/index.ts +0 -10
  121. package/app/server/middleware/rateLimit.ts +0 -193
  122. package/app/server/middleware/requestLogging.ts +0 -215
  123. package/app/server/middleware/validation.ts +0 -270
  124. package/app/server/routes/config.ts +0 -145
  125. package/app/server/routes/crypto-auth-demo.routes.ts +0 -167
  126. package/app/server/routes/example-with-crypto-auth.routes.ts +0 -235
  127. package/app/server/routes/exemplo-posts.routes.ts +0 -161
  128. package/app/server/routes/upload.ts +0 -92
  129. package/app/server/services/NotificationService.ts +0 -302
  130. package/app/server/services/UserService.ts +0 -222
  131. package/app/server/services/index.ts +0 -46
  132. package/app/server/types/index.ts +0 -1
@@ -1,1044 +0,0 @@
1
- // 🔥 System Monitor Dashboard Component
2
-
3
- import { useState } from 'react'
4
- import { useHybridLiveComponent } from '@/core/client'
5
- import {
6
- FaServer,
7
- FaHome,
8
- FaMemory,
9
- FaHeartbeat,
10
- FaChartLine,
11
- FaClock,
12
- FaWifi,
13
- FaPlay,
14
- FaPause,
15
- FaSync,
16
- FaTrash,
17
- FaInfo,
18
- FaExclamationTriangle,
19
- FaCheckCircle,
20
- FaTimesCircle,
21
- FaEye,
22
- FaBolt,
23
- FaDatabase,
24
- FaStop
25
- } from 'react-icons/fa'
26
-
27
- export interface SystemMonitorState {
28
- totalComponents: number
29
- activeConnections: number
30
- totalRooms: number
31
- messagesPerSecond: number
32
- averageResponseTime: number
33
- componentsByType: Record<string, number>
34
- roomDetails: Record<string, number>
35
- memoryUsage: {
36
- used: number
37
- total: number
38
- percentage: number
39
- }
40
- recentConnections: Array<{
41
- id: string
42
- timestamp: number
43
- componentType: string
44
- status: 'connected' | 'disconnected' | 'rehydrated'
45
- }>
46
- recentMessages: Array<{
47
- id: string
48
- timestamp: number
49
- type: string
50
- componentId: string
51
- success: boolean
52
- responseTime?: number
53
- }>
54
- systemHealth: {
55
- status: 'healthy' | 'warning' | 'critical'
56
- uptime: number
57
- lastRestart: number
58
- errors: number
59
- warnings: number
60
- }
61
- autoRefresh: boolean
62
- refreshInterval: number
63
- lastUpdated: number
64
- }
65
-
66
- const initialState: SystemMonitorState = {
67
- totalComponents: 0,
68
- activeConnections: 0,
69
- totalRooms: 0,
70
- messagesPerSecond: 0,
71
- averageResponseTime: 0,
72
- componentsByType: {},
73
- roomDetails: {},
74
- memoryUsage: {
75
- used: 0,
76
- total: 0,
77
- percentage: 0
78
- },
79
- recentConnections: [],
80
- recentMessages: [],
81
- systemHealth: {
82
- status: 'healthy',
83
- uptime: 0,
84
- lastRestart: Date.now(),
85
- errors: 0,
86
- warnings: 0
87
- },
88
- autoRefresh: true,
89
- refreshInterval: 2000,
90
- lastUpdated: Date.now()
91
- }
92
-
93
- export function SystemMonitor() {
94
- const { state, call, connected, status, error } = useHybridLiveComponent<SystemMonitorState>(
95
- 'SystemMonitor',
96
- initialState,
97
- { debug: true }
98
- )
99
-
100
- const [selectedTab, setSelectedTab] = useState<'overview' | 'components' | 'activity' | 'system'>('overview')
101
-
102
- // Show loading state
103
- if (!connected || status !== 'synced') {
104
- const getStatusMessage = () => {
105
- switch (status) {
106
- case 'connecting':
107
- return '🔄 Conectando ao monitoramento...'
108
- case 'reconnecting':
109
- return '🔄 Reconectando sistema...'
110
- case 'mounting':
111
- return '🚀 Iniciando monitoramento...'
112
- case 'loading':
113
- return '⏳ Carregando métricas...'
114
- case 'error':
115
- return '❌ Erro no monitoramento'
116
- default:
117
- return '🔄 Preparando sistema...'
118
- }
119
- }
120
-
121
- return (
122
- <div style={{
123
- padding: '4rem',
124
- textAlign: 'center',
125
- backgroundColor: '#f8fafc',
126
- minHeight: '100vh',
127
- display: 'flex',
128
- flexDirection: 'column',
129
- alignItems: 'center',
130
- justifyContent: 'center'
131
- }}>
132
- <FaServer size={48} style={{ marginBottom: '2rem', color: '#6b7280' }} />
133
- <h2 style={{ color: '#374151', marginBottom: '1rem' }}>
134
- Sistema de Monitoramento
135
- </h2>
136
- <p style={{ color: '#6b7280', marginBottom: '2rem' }}>
137
- {getStatusMessage()}
138
- </p>
139
- {error && (
140
- <div style={{
141
- backgroundColor: '#fee2e2',
142
- color: '#dc2626',
143
- padding: '1rem',
144
- borderRadius: '8px',
145
- border: '1px solid #fecaca'
146
- }}>
147
- {error}
148
- </div>
149
- )}
150
- </div>
151
- )
152
- }
153
-
154
- const handleToggleAutoRefresh = async () => {
155
- try {
156
- await call('toggleAutoRefresh')
157
- } catch (error) {
158
- console.error('Toggle auto-refresh error:', error)
159
- }
160
- }
161
-
162
- const handleRefreshMetrics = async () => {
163
- try {
164
- await call('refreshMetrics')
165
- } catch (error) {
166
- console.error('Refresh metrics error:', error)
167
- }
168
- }
169
-
170
- const handleEmergencyStop = async () => {
171
- try {
172
- await call('emergencyStop')
173
- } catch (error) {
174
- console.error('Emergency stop error:', error)
175
- }
176
- }
177
-
178
- const handleClearActivity = async () => {
179
- try {
180
- await call('clearActivity')
181
- } catch (error) {
182
- console.error('Clear activity error:', error)
183
- }
184
- }
185
-
186
- const formatUptime = (seconds: number) => {
187
- const hours = Math.floor(seconds / 3600)
188
- const minutes = Math.floor((seconds % 3600) / 60)
189
- const secs = seconds % 60
190
- return `${hours}h ${minutes}m ${secs}s`
191
- }
192
-
193
- const formatTimestamp = (timestamp: number) => {
194
- return new Date(timestamp).toLocaleTimeString()
195
- }
196
-
197
- const getHealthIcon = (status: string) => {
198
- switch (status) {
199
- case 'healthy':
200
- return <FaCheckCircle style={{ color: '#10b981' }} />
201
- case 'warning':
202
- return <FaExclamationTriangle style={{ color: '#f59e0b' }} />
203
- case 'critical':
204
- return <FaTimesCircle style={{ color: '#ef4444' }} />
205
- default:
206
- return <FaHeartbeat style={{ color: '#6b7280' }} />
207
- }
208
- }
209
-
210
- const getHealthColor = (status: string) => {
211
- switch (status) {
212
- case 'healthy':
213
- return '#10b981'
214
- case 'warning':
215
- return '#f59e0b'
216
- case 'critical':
217
- return '#ef4444'
218
- default:
219
- return '#6b7280'
220
- }
221
- }
222
-
223
- const getConnectionStatusIcon = (status: string) => {
224
- switch (status) {
225
- case 'connected':
226
- return <FaWifi style={{ color: '#10b981' }} />
227
- case 'disconnected':
228
- return <FaTimesCircle style={{ color: '#ef4444' }} />
229
- case 'rehydrated':
230
- return <FaSync style={{ color: '#3b82f6' }} />
231
- default:
232
- return <FaWifi style={{ color: '#6b7280' }} />
233
- }
234
- }
235
-
236
- return (
237
- <div style={{
238
- padding: '2rem',
239
- backgroundColor: '#f8fafc',
240
- minHeight: '100vh'
241
- }}>
242
- {/* Header */}
243
- <div style={{
244
- marginBottom: '2rem'
245
- }}>
246
- <div style={{
247
- display: 'flex',
248
- alignItems: 'center',
249
- justifyContent: 'space-between',
250
- marginBottom: '1rem'
251
- }}>
252
- <div style={{
253
- display: 'flex',
254
- alignItems: 'center',
255
- gap: '1rem'
256
- }}>
257
- <FaServer size={32} style={{ color: '#374151' }} />
258
- <div>
259
- <h1 style={{
260
- color: '#374151',
261
- margin: 0,
262
- fontSize: '2rem'
263
- }}>
264
- 🔥 Sistema de Monitoramento
265
- </h1>
266
- <p style={{
267
- color: '#6b7280',
268
- margin: 0,
269
- fontSize: '1.1rem'
270
- }}>
271
- Monitoramento em tempo real dos Live Components
272
- </p>
273
- </div>
274
- </div>
275
-
276
- {/* Controls */}
277
- <div style={{
278
- display: 'flex',
279
- gap: '1rem',
280
- alignItems: 'center'
281
- }}>
282
- <button
283
- onClick={handleToggleAutoRefresh}
284
- style={{
285
- display: 'flex',
286
- alignItems: 'center',
287
- gap: '0.5rem',
288
- padding: '0.75rem 1rem',
289
- borderRadius: '8px',
290
- border: 'none',
291
- cursor: 'pointer',
292
- backgroundColor: state.autoRefresh ? '#10b981' : '#6b7280',
293
- color: 'white',
294
- fontSize: '0.9rem'
295
- }}
296
- >
297
- {state.autoRefresh ? <FaPause /> : <FaPlay />}
298
- {state.autoRefresh ? 'Pausar' : 'Iniciar'}
299
- </button>
300
-
301
- <button
302
- onClick={handleRefreshMetrics}
303
- style={{
304
- display: 'flex',
305
- alignItems: 'center',
306
- gap: '0.5rem',
307
- padding: '0.75rem 1rem',
308
- borderRadius: '8px',
309
- border: '1px solid #d1d5db',
310
- cursor: 'pointer',
311
- backgroundColor: 'white',
312
- color: '#374151',
313
- fontSize: '0.9rem'
314
- }}
315
- >
316
- <FaSync />
317
- Atualizar
318
- </button>
319
-
320
- <button
321
- onClick={handleClearActivity}
322
- style={{
323
- display: 'flex',
324
- alignItems: 'center',
325
- gap: '0.5rem',
326
- padding: '0.75rem 1rem',
327
- borderRadius: '8px',
328
- border: '1px solid #d1d5db',
329
- cursor: 'pointer',
330
- backgroundColor: 'white',
331
- color: '#ef4444',
332
- fontSize: '0.9rem'
333
- }}
334
- >
335
- <FaTrash />
336
- Limpar
337
- </button>
338
-
339
- <button
340
- onClick={handleEmergencyStop}
341
- style={{
342
- display: 'flex',
343
- alignItems: 'center',
344
- gap: '0.5rem',
345
- padding: '0.75rem 1rem',
346
- borderRadius: '8px',
347
- border: '2px solid #dc2626',
348
- cursor: 'pointer',
349
- backgroundColor: '#dc2626',
350
- color: 'white',
351
- fontSize: '0.9rem',
352
- fontWeight: 'bold'
353
- }}
354
- >
355
- <FaStop />
356
- 🚨 PARAR TUDO
357
- </button>
358
- </div>
359
- </div>
360
-
361
- {/* Status Bar */}
362
- <div style={{
363
- display: 'flex',
364
- alignItems: 'center',
365
- gap: '2rem',
366
- padding: '1rem',
367
- backgroundColor: 'white',
368
- borderRadius: '12px',
369
- boxShadow: '0 1px 3px rgba(0, 0, 0, 0.1)'
370
- }}>
371
- <div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}>
372
- {getHealthIcon(state.systemHealth.status)}
373
- <span style={{
374
- color: getHealthColor(state.systemHealth.status),
375
- fontWeight: 'bold'
376
- }}>
377
- {state.systemHealth.status.charAt(0).toUpperCase() + state.systemHealth.status.slice(1)}
378
- </span>
379
- </div>
380
-
381
- <div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}>
382
- <FaClock style={{ color: '#6b7280' }} />
383
- <span style={{ color: '#374151' }}>
384
- Uptime: {formatUptime(state.systemHealth.uptime)}
385
- </span>
386
- </div>
387
-
388
- <div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}>
389
- <FaSync style={{ color: '#6b7280' }} />
390
- <span style={{ color: '#374151' }}>
391
- Auto-refresh: {state.autoRefresh ? 'ON' : 'OFF'}
392
- ({state.refreshInterval}ms)
393
- </span>
394
- </div>
395
-
396
- <div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}>
397
- <FaClock style={{ color: '#6b7280' }} />
398
- <span style={{ color: '#374151' }}>
399
- Última atualização: {formatTimestamp(state.lastUpdated)}
400
- </span>
401
- </div>
402
- </div>
403
- </div>
404
-
405
- {/* Navigation Tabs */}
406
- <div style={{
407
- display: 'flex',
408
- gap: '1rem',
409
- marginBottom: '2rem'
410
- }}>
411
- {[
412
- { id: 'overview', label: 'Visão Geral', icon: <FaChartLine /> },
413
- { id: 'components', label: 'Componentes', icon: <FaBolt /> },
414
- { id: 'activity', label: 'Atividade', icon: <FaEye /> },
415
- { id: 'system', label: 'Sistema', icon: <FaDatabase /> }
416
- ].map(tab => (
417
- <button
418
- key={tab.id}
419
- onClick={() => setSelectedTab(tab.id as any)}
420
- style={{
421
- display: 'flex',
422
- alignItems: 'center',
423
- gap: '0.5rem',
424
- padding: '1rem 1.5rem',
425
- borderRadius: '8px',
426
- border: 'none',
427
- cursor: 'pointer',
428
- backgroundColor: selectedTab === tab.id ? '#3b82f6' : 'white',
429
- color: selectedTab === tab.id ? 'white' : '#374151',
430
- fontSize: '0.95rem',
431
- boxShadow: '0 1px 3px rgba(0, 0, 0, 0.1)'
432
- }}
433
- >
434
- {tab.icon}
435
- {tab.label}
436
- </button>
437
- ))}
438
- </div>
439
-
440
- {/* Content */}
441
- {selectedTab === 'overview' && (
442
- <div>
443
- {/* Metrics Cards */}
444
- <div style={{
445
- display: 'grid',
446
- gridTemplateColumns: 'repeat(auto-fit, minmax(250px, 1fr))',
447
- gap: '1.5rem',
448
- marginBottom: '2rem'
449
- }}>
450
- {[
451
- {
452
- title: 'Componentes Ativos',
453
- value: state.totalComponents,
454
- icon: <FaBolt />,
455
- color: '#3b82f6',
456
- subtitle: 'Live Components'
457
- },
458
- {
459
- title: 'Conexões WebSocket',
460
- value: state.activeConnections,
461
- icon: <FaWifi />,
462
- color: '#10b981',
463
- subtitle: 'Conexões ativas'
464
- },
465
- {
466
- title: 'Salas',
467
- value: state.totalRooms,
468
- icon: <FaHome />,
469
- color: '#f59e0b',
470
- subtitle: 'Rooms ativas'
471
- },
472
- {
473
- title: 'Mensagens/seg',
474
- value: state.messagesPerSecond,
475
- icon: <FaChartLine />,
476
- color: '#8b5cf6',
477
- subtitle: 'Taxa de mensagens'
478
- },
479
- {
480
- title: 'Tempo de Resposta',
481
- value: `${state.averageResponseTime}ms`,
482
- icon: <FaClock />,
483
- color: '#06b6d4',
484
- subtitle: 'Tempo médio'
485
- },
486
- {
487
- title: 'Uso de Memória',
488
- value: `${state.memoryUsage.percentage}%`,
489
- icon: <FaMemory />,
490
- color: state.memoryUsage.percentage > 75 ? '#ef4444' : '#10b981',
491
- subtitle: `${state.memoryUsage.used}MB / ${state.memoryUsage.total}MB`
492
- }
493
- ].map((metric, index) => (
494
- <div key={index} style={{
495
- backgroundColor: 'white',
496
- padding: '2rem',
497
- borderRadius: '16px',
498
- boxShadow: '0 4px 6px rgba(0, 0, 0, 0.1)',
499
- border: '1px solid #e5e7eb'
500
- }}>
501
- <div style={{
502
- display: 'flex',
503
- alignItems: 'center',
504
- gap: '1rem',
505
- marginBottom: '1rem'
506
- }}>
507
- <div style={{
508
- backgroundColor: metric.color,
509
- padding: '0.75rem',
510
- borderRadius: '12px',
511
- color: 'white',
512
- fontSize: '1.2rem'
513
- }}>
514
- {metric.icon}
515
- </div>
516
- <div>
517
- <h3 style={{
518
- margin: 0,
519
- fontSize: '1rem',
520
- color: '#374151'
521
- }}>
522
- {metric.title}
523
- </h3>
524
- <p style={{
525
- margin: 0,
526
- fontSize: '1.8rem',
527
- fontWeight: 'bold',
528
- color: metric.color
529
- }}>
530
- {metric.value}
531
- </p>
532
- <p style={{
533
- margin: 0,
534
- fontSize: '0.9rem',
535
- color: '#6b7280'
536
- }}>
537
- {metric.subtitle}
538
- </p>
539
- </div>
540
- </div>
541
- </div>
542
- ))}
543
- </div>
544
-
545
- {/* System Health */}
546
- <div style={{
547
- backgroundColor: 'white',
548
- padding: '2rem',
549
- borderRadius: '16px',
550
- boxShadow: '0 4px 6px rgba(0, 0, 0, 0.1)',
551
- marginBottom: '2rem'
552
- }}>
553
- <h3 style={{
554
- color: '#374151',
555
- marginBottom: '1rem',
556
- display: 'flex',
557
- alignItems: 'center',
558
- gap: '0.5rem'
559
- }}>
560
- <FaHeartbeat />
561
- Status do Sistema
562
- </h3>
563
-
564
- <div style={{
565
- display: 'grid',
566
- gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))',
567
- gap: '1rem'
568
- }}>
569
- <div style={{
570
- padding: '1rem',
571
- backgroundColor: '#f8fafc',
572
- borderRadius: '8px',
573
- border: '1px solid #e2e8f0'
574
- }}>
575
- <div style={{
576
- display: 'flex',
577
- alignItems: 'center',
578
- gap: '0.5rem',
579
- marginBottom: '0.5rem'
580
- }}>
581
- {getHealthIcon(state.systemHealth.status)}
582
- <span style={{ fontWeight: 'bold', color: '#374151' }}>
583
- Status Geral
584
- </span>
585
- </div>
586
- <p style={{
587
- margin: 0,
588
- color: getHealthColor(state.systemHealth.status),
589
- fontWeight: 'bold'
590
- }}>
591
- {state.systemHealth.status.toUpperCase()}
592
- </p>
593
- </div>
594
-
595
- <div style={{
596
- padding: '1rem',
597
- backgroundColor: '#f8fafc',
598
- borderRadius: '8px',
599
- border: '1px solid #e2e8f0'
600
- }}>
601
- <div style={{
602
- display: 'flex',
603
- alignItems: 'center',
604
- gap: '0.5rem',
605
- marginBottom: '0.5rem'
606
- }}>
607
- <FaTimesCircle style={{ color: '#ef4444' }} />
608
- <span style={{ fontWeight: 'bold', color: '#374151' }}>
609
- Erros
610
- </span>
611
- </div>
612
- <p style={{ margin: 0, color: '#ef4444', fontWeight: 'bold' }}>
613
- {state.systemHealth.errors}
614
- </p>
615
- </div>
616
-
617
- <div style={{
618
- padding: '1rem',
619
- backgroundColor: '#f8fafc',
620
- borderRadius: '8px',
621
- border: '1px solid #e2e8f0'
622
- }}>
623
- <div style={{
624
- display: 'flex',
625
- alignItems: 'center',
626
- gap: '0.5rem',
627
- marginBottom: '0.5rem'
628
- }}>
629
- <FaExclamationTriangle style={{ color: '#f59e0b' }} />
630
- <span style={{ fontWeight: 'bold', color: '#374151' }}>
631
- Avisos
632
- </span>
633
- </div>
634
- <p style={{ margin: 0, color: '#f59e0b', fontWeight: 'bold' }}>
635
- {state.systemHealth.warnings}
636
- </p>
637
- </div>
638
-
639
- <div style={{
640
- padding: '1rem',
641
- backgroundColor: '#f8fafc',
642
- borderRadius: '8px',
643
- border: '1px solid #e2e8f0'
644
- }}>
645
- <div style={{
646
- display: 'flex',
647
- alignItems: 'center',
648
- gap: '0.5rem',
649
- marginBottom: '0.5rem'
650
- }}>
651
- <FaClock style={{ color: '#6b7280' }} />
652
- <span style={{ fontWeight: 'bold', color: '#374151' }}>
653
- Uptime
654
- </span>
655
- </div>
656
- <p style={{ margin: 0, color: '#374151', fontWeight: 'bold' }}>
657
- {formatUptime(state.systemHealth.uptime)}
658
- </p>
659
- </div>
660
- </div>
661
- </div>
662
- </div>
663
- )}
664
-
665
- {selectedTab === 'components' && (
666
- <div>
667
- {/* Components by Type */}
668
- <div style={{
669
- backgroundColor: 'white',
670
- padding: '2rem',
671
- borderRadius: '16px',
672
- boxShadow: '0 4px 6px rgba(0, 0, 0, 0.1)',
673
- marginBottom: '2rem'
674
- }}>
675
- <h3 style={{
676
- color: '#374151',
677
- marginBottom: '1.5rem',
678
- display: 'flex',
679
- alignItems: 'center',
680
- gap: '0.5rem'
681
- }}>
682
- <FaBolt />
683
- Componentes por Tipo
684
- </h3>
685
-
686
- <div style={{
687
- display: 'grid',
688
- gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))',
689
- gap: '1rem'
690
- }}>
691
- {Object.entries(state.componentsByType).map(([type, count]) => {
692
- const countNum = count as number
693
- return (
694
- <div key={type} style={{
695
- padding: '1.5rem',
696
- backgroundColor: '#f8fafc',
697
- borderRadius: '12px',
698
- border: '1px solid #e2e8f0',
699
- textAlign: 'center'
700
- }}>
701
- <h4 style={{
702
- margin: '0 0 0.5rem 0',
703
- color: '#374151',
704
- fontSize: '1rem'
705
- }}>
706
- {type}
707
- </h4>
708
- <p style={{
709
- margin: 0,
710
- fontSize: '2rem',
711
- fontWeight: 'bold',
712
- color: countNum > 0 ? '#10b981' : '#6b7280'
713
- }}>
714
- {countNum}
715
- </p>
716
- <p style={{
717
- margin: 0,
718
- fontSize: '0.9rem',
719
- color: '#6b7280'
720
- }}>
721
- {countNum === 1 ? 'instância' : 'instâncias'}
722
- </p>
723
- </div>
724
- )
725
- })}
726
- </div>
727
- </div>
728
-
729
- {/* Room Details */}
730
- <div style={{
731
- backgroundColor: 'white',
732
- padding: '2rem',
733
- borderRadius: '16px',
734
- boxShadow: '0 4px 6px rgba(0, 0, 0, 0.1)'
735
- }}>
736
- <h3 style={{
737
- color: '#374151',
738
- marginBottom: '1.5rem',
739
- display: 'flex',
740
- alignItems: 'center',
741
- gap: '0.5rem'
742
- }}>
743
- <FaHome />
744
- Salas Ativas
745
- </h3>
746
-
747
- {Object.keys(state.roomDetails).length > 0 ? (
748
- <div style={{
749
- display: 'grid',
750
- gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))',
751
- gap: '1rem'
752
- }}>
753
- {Object.entries(state.roomDetails).map(([room, count]) => {
754
- const countNum = count as number
755
- return (
756
- <div key={room} style={{
757
- padding: '1.5rem',
758
- backgroundColor: '#f0f9ff',
759
- borderRadius: '12px',
760
- border: '1px solid #bae6fd',
761
- textAlign: 'center'
762
- }}>
763
- <h4 style={{
764
- margin: '0 0 0.5rem 0',
765
- color: '#0369a1',
766
- fontSize: '1rem'
767
- }}>
768
- {room}
769
- </h4>
770
- <p style={{
771
- margin: 0,
772
- fontSize: '2rem',
773
- fontWeight: 'bold',
774
- color: '#0284c7'
775
- }}>
776
- {countNum}
777
- </p>
778
- <p style={{
779
- margin: 0,
780
- fontSize: '0.9rem',
781
- color: '#0369a1'
782
- }}>
783
- {countNum === 1 ? 'componente' : 'componentes'}
784
- </p>
785
- </div>
786
- )
787
- })}
788
- </div>
789
- ) : (
790
- <div style={{
791
- textAlign: 'center',
792
- padding: '3rem',
793
- color: '#6b7280'
794
- }}>
795
- <FaHome size={48} style={{ marginBottom: '1rem', opacity: 0.5 }} />
796
- <p>Nenhuma sala ativa no momento</p>
797
- </div>
798
- )}
799
- </div>
800
- </div>
801
- )}
802
-
803
- {selectedTab === 'activity' && (
804
- <div style={{
805
- display: 'grid',
806
- gridTemplateColumns: '1fr 1fr',
807
- gap: '2rem'
808
- }}>
809
- {/* Recent Connections */}
810
- <div style={{
811
- backgroundColor: 'white',
812
- padding: '2rem',
813
- borderRadius: '16px',
814
- boxShadow: '0 4px 6px rgba(0, 0, 0, 0.1)'
815
- }}>
816
- <h3 style={{
817
- color: '#374151',
818
- marginBottom: '1.5rem',
819
- display: 'flex',
820
- alignItems: 'center',
821
- gap: '0.5rem'
822
- }}>
823
- <FaWifi />
824
- Conexões Recentes
825
- </h3>
826
-
827
- {state.recentConnections.length > 0 ? (
828
- <div style={{
829
- maxHeight: '400px',
830
- overflowY: 'auto'
831
- }}>
832
- {state.recentConnections.slice(0, 20).map(connection => (
833
- <div key={connection.id} style={{
834
- display: 'flex',
835
- alignItems: 'center',
836
- gap: '1rem',
837
- padding: '1rem',
838
- marginBottom: '0.5rem',
839
- backgroundColor: '#f8fafc',
840
- borderRadius: '8px',
841
- border: '1px solid #e2e8f0'
842
- }}>
843
- {getConnectionStatusIcon(connection.status)}
844
- <div style={{ flex: 1 }}>
845
- <p style={{
846
- margin: 0,
847
- fontWeight: 'bold',
848
- color: '#374151'
849
- }}>
850
- {connection.componentType}
851
- </p>
852
- <p style={{
853
- margin: 0,
854
- fontSize: '0.9rem',
855
- color: '#6b7280'
856
- }}>
857
- {connection.status} - {formatTimestamp(connection.timestamp)}
858
- </p>
859
- </div>
860
- </div>
861
- ))}
862
- </div>
863
- ) : (
864
- <div style={{
865
- textAlign: 'center',
866
- padding: '3rem',
867
- color: '#6b7280'
868
- }}>
869
- <FaWifi size={48} style={{ marginBottom: '1rem', opacity: 0.5 }} />
870
- <p>Nenhuma conexão recente</p>
871
- </div>
872
- )}
873
- </div>
874
-
875
- {/* Recent Messages */}
876
- <div style={{
877
- backgroundColor: 'white',
878
- padding: '2rem',
879
- borderRadius: '16px',
880
- boxShadow: '0 4px 6px rgba(0, 0, 0, 0.1)'
881
- }}>
882
- <h3 style={{
883
- color: '#374151',
884
- marginBottom: '1.5rem',
885
- display: 'flex',
886
- alignItems: 'center',
887
- gap: '0.5rem'
888
- }}>
889
- <FaBolt />
890
- Mensagens Recentes
891
- </h3>
892
-
893
- {state.recentMessages.length > 0 ? (
894
- <div style={{
895
- maxHeight: '400px',
896
- overflowY: 'auto'
897
- }}>
898
- {state.recentMessages.slice(0, 20).map(message => (
899
- <div key={message.id} style={{
900
- display: 'flex',
901
- alignItems: 'center',
902
- gap: '1rem',
903
- padding: '1rem',
904
- marginBottom: '0.5rem',
905
- backgroundColor: '#f8fafc',
906
- borderRadius: '8px',
907
- border: '1px solid #e2e8f0'
908
- }}>
909
- {message.success ?
910
- <FaCheckCircle style={{ color: '#10b981' }} /> :
911
- <FaTimesCircle style={{ color: '#ef4444' }} />
912
- }
913
- <div style={{ flex: 1 }}>
914
- <p style={{
915
- margin: 0,
916
- fontWeight: 'bold',
917
- color: '#374151'
918
- }}>
919
- {message.type}
920
- </p>
921
- <p style={{
922
- margin: 0,
923
- fontSize: '0.9rem',
924
- color: '#6b7280'
925
- }}>
926
- {message.componentId.substring(0, 8)}... - {formatTimestamp(message.timestamp)}
927
- {message.responseTime && ` (${message.responseTime}ms)`}
928
- </p>
929
- </div>
930
- </div>
931
- ))}
932
- </div>
933
- ) : (
934
- <div style={{
935
- textAlign: 'center',
936
- padding: '3rem',
937
- color: '#6b7280'
938
- }}>
939
- <FaBolt size={48} style={{ marginBottom: '1rem', opacity: 0.5 }} />
940
- <p>Nenhuma mensagem recente</p>
941
- </div>
942
- )}
943
- </div>
944
- </div>
945
- )}
946
-
947
- {selectedTab === 'system' && (
948
- <div>
949
- <div style={{
950
- backgroundColor: 'white',
951
- padding: '2rem',
952
- borderRadius: '16px',
953
- boxShadow: '0 4px 6px rgba(0, 0, 0, 0.1)'
954
- }}>
955
- <h3 style={{
956
- color: '#374151',
957
- marginBottom: '1.5rem',
958
- display: 'flex',
959
- alignItems: 'center',
960
- gap: '0.5rem'
961
- }}>
962
- <FaInfo />
963
- Informações do Sistema
964
- </h3>
965
-
966
- <div style={{
967
- display: 'grid',
968
- gridTemplateColumns: 'repeat(auto-fit, minmax(300px, 1fr))',
969
- gap: '1.5rem'
970
- }}>
971
- <div style={{
972
- padding: '1.5rem',
973
- backgroundColor: '#f8fafc',
974
- borderRadius: '12px',
975
- border: '1px solid #e2e8f0'
976
- }}>
977
- <h4 style={{ color: '#374151', marginBottom: '1rem' }}>
978
- Performance
979
- </h4>
980
- <div style={{ display: 'flex', flexDirection: 'column', gap: '0.5rem' }}>
981
- <div style={{ display: 'flex', justifyContent: 'space-between' }}>
982
- <span style={{ color: '#6b7280' }}>Memória Usada:</span>
983
- <span style={{ color: '#374151', fontWeight: 'bold' }}>
984
- {state.memoryUsage.used}MB
985
- </span>
986
- </div>
987
- <div style={{ display: 'flex', justifyContent: 'space-between' }}>
988
- <span style={{ color: '#6b7280' }}>Memória Total:</span>
989
- <span style={{ color: '#374151', fontWeight: 'bold' }}>
990
- {state.memoryUsage.total}MB
991
- </span>
992
- </div>
993
- <div style={{ display: 'flex', justifyContent: 'space-between' }}>
994
- <span style={{ color: '#6b7280' }}>Uso de Memória:</span>
995
- <span style={{
996
- color: state.memoryUsage.percentage > 75 ? '#ef4444' : '#10b981',
997
- fontWeight: 'bold'
998
- }}>
999
- {state.memoryUsage.percentage}%
1000
- </span>
1001
- </div>
1002
- </div>
1003
- </div>
1004
-
1005
- <div style={{
1006
- padding: '1.5rem',
1007
- backgroundColor: '#f8fafc',
1008
- borderRadius: '12px',
1009
- border: '1px solid #e2e8f0'
1010
- }}>
1011
- <h4 style={{ color: '#374151', marginBottom: '1rem' }}>
1012
- Configurações
1013
- </h4>
1014
- <div style={{ display: 'flex', flexDirection: 'column', gap: '0.5rem' }}>
1015
- <div style={{ display: 'flex', justifyContent: 'space-between' }}>
1016
- <span style={{ color: '#6b7280' }}>Auto-refresh:</span>
1017
- <span style={{
1018
- color: state.autoRefresh ? '#10b981' : '#ef4444',
1019
- fontWeight: 'bold'
1020
- }}>
1021
- {state.autoRefresh ? 'ATIVO' : 'INATIVO'}
1022
- </span>
1023
- </div>
1024
- <div style={{ display: 'flex', justifyContent: 'space-between' }}>
1025
- <span style={{ color: '#6b7280' }}>Intervalo:</span>
1026
- <span style={{ color: '#374151', fontWeight: 'bold' }}>
1027
- {state.refreshInterval}ms
1028
- </span>
1029
- </div>
1030
- <div style={{ display: 'flex', justifyContent: 'space-between' }}>
1031
- <span style={{ color: '#6b7280' }}>Última atualização:</span>
1032
- <span style={{ color: '#374151', fontWeight: 'bold' }}>
1033
- {formatTimestamp(state.lastUpdated)}
1034
- </span>
1035
- </div>
1036
- </div>
1037
- </div>
1038
- </div>
1039
- </div>
1040
- </div>
1041
- )}
1042
- </div>
1043
- )
1044
- }