create-fluxstack 1.0.13 β 1.0.14
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.
- package/.env.example +29 -29
- package/app/client/README.md +69 -69
- package/app/client/index.html +14 -13
- package/app/client/src/App.tsx +157 -524
- package/app/client/src/components/ErrorBoundary.tsx +107 -0
- package/app/client/src/components/ErrorDisplay.css +365 -0
- package/app/client/src/components/ErrorDisplay.tsx +258 -0
- package/app/client/src/components/FluxStackConfig.tsx +1321 -0
- package/app/client/src/components/HybridLiveCounter.tsx +140 -0
- package/app/client/src/components/LiveClock.tsx +286 -0
- package/app/client/src/components/MainLayout.tsx +390 -0
- package/app/client/src/components/SidebarNavigation.tsx +391 -0
- package/app/client/src/components/StateDemo.tsx +178 -0
- package/app/client/src/components/SystemMonitor.tsx +1038 -0
- package/app/client/src/components/Teste.tsx +104 -0
- package/app/client/src/components/UserProfile.tsx +809 -0
- package/app/client/src/hooks/useAuth.ts +39 -0
- package/app/client/src/hooks/useNotifications.ts +56 -0
- package/app/client/src/lib/eden-api.ts +189 -53
- package/app/client/src/lib/errors.ts +340 -0
- package/app/client/src/lib/hooks/useErrorHandler.ts +258 -0
- package/app/client/src/lib/index.ts +45 -0
- package/app/client/src/main.tsx +3 -2
- package/app/client/src/pages/ApiDocs.tsx +182 -0
- package/app/client/src/pages/Demo.tsx +174 -0
- package/app/client/src/pages/HybridLive.tsx +263 -0
- package/app/client/src/pages/Overview.tsx +155 -0
- package/app/client/src/store/README.md +43 -0
- package/app/client/src/store/index.ts +16 -0
- package/app/client/src/store/slices/uiSlice.ts +151 -0
- package/app/client/src/store/slices/userSlice.ts +161 -0
- package/app/client/src/test/README.md +257 -0
- package/app/client/src/test/setup.ts +70 -0
- package/app/client/src/test/types.ts +12 -0
- package/app/client/src/vite-env.d.ts +1 -1
- package/app/client/tsconfig.app.json +44 -43
- package/app/client/tsconfig.json +7 -7
- package/app/client/tsconfig.node.json +25 -25
- package/app/client/zustand-setup.md +65 -0
- package/app/server/controllers/users.controller.ts +68 -68
- package/app/server/index.ts +9 -1
- package/app/server/live/CounterComponent.ts +191 -0
- package/app/server/live/FluxStackConfig.ts +529 -0
- package/app/server/live/LiveClockComponent.ts +214 -0
- package/app/server/live/SidebarNavigation.ts +156 -0
- package/app/server/live/SystemMonitor.ts +594 -0
- package/app/server/live/SystemMonitorIntegration.ts +151 -0
- package/app/server/live/TesteComponent.ts +87 -0
- package/app/server/live/UserProfileComponent.ts +135 -0
- package/app/server/live/register-components.ts +28 -0
- package/app/server/middleware/auth.ts +136 -0
- package/app/server/middleware/errorHandling.ts +250 -0
- package/app/server/middleware/index.ts +10 -0
- package/app/server/middleware/rateLimit.ts +193 -0
- package/app/server/middleware/requestLogging.ts +215 -0
- package/app/server/middleware/validation.ts +270 -0
- package/app/server/routes/index.ts +14 -2
- package/app/server/routes/upload.ts +92 -0
- package/app/server/routes/users.routes.ts +2 -9
- package/app/server/services/NotificationService.ts +302 -0
- package/app/server/services/UserService.ts +222 -0
- package/app/server/services/index.ts +46 -0
- package/core/cli/commands/plugin-deps.ts +263 -0
- package/core/cli/generators/README.md +339 -0
- package/core/cli/generators/component.ts +770 -0
- package/core/cli/generators/controller.ts +299 -0
- package/core/cli/generators/index.ts +144 -0
- package/core/cli/generators/interactive.ts +228 -0
- package/core/cli/generators/prompts.ts +83 -0
- package/core/cli/generators/route.ts +513 -0
- package/core/cli/generators/service.ts +465 -0
- package/core/cli/generators/template-engine.ts +154 -0
- package/core/cli/generators/types.ts +71 -0
- package/core/cli/generators/utils.ts +192 -0
- package/core/cli/index.ts +69 -0
- package/core/cli/plugin-discovery.ts +16 -85
- package/core/client/fluxstack.ts +17 -0
- package/core/client/hooks/index.ts +7 -0
- package/core/client/hooks/state-validator.ts +130 -0
- package/core/client/hooks/useAuth.ts +49 -0
- package/core/client/hooks/useChunkedUpload.ts +258 -0
- package/core/client/hooks/useHybridLiveComponent.ts +967 -0
- package/core/client/hooks/useWebSocket.ts +373 -0
- package/core/client/index.ts +47 -0
- package/core/client/state/createStore.ts +193 -0
- package/core/client/state/index.ts +15 -0
- package/core/config/env-dynamic.ts +1 -1
- package/core/config/env.ts +2 -1
- package/core/config/runtime-config.ts +3 -3
- package/core/config/schema.ts +84 -49
- package/core/framework/server.ts +30 -0
- package/core/index.ts +25 -0
- package/core/live/ComponentRegistry.ts +399 -0
- package/core/live/types.ts +164 -0
- package/core/plugins/built-in/live-components/commands/create-live-component.ts +1201 -0
- package/core/plugins/built-in/live-components/index.ts +27 -0
- package/core/plugins/built-in/logger/index.ts +1 -1
- package/core/plugins/built-in/monitoring/index.ts +1 -1
- package/core/plugins/built-in/static/index.ts +1 -1
- package/core/plugins/built-in/swagger/index.ts +1 -1
- package/core/plugins/built-in/vite/index.ts +1 -1
- package/core/plugins/dependency-manager.ts +384 -0
- package/core/plugins/index.ts +5 -1
- package/core/plugins/manager.ts +7 -3
- package/core/plugins/registry.ts +88 -10
- package/core/plugins/types.ts +11 -11
- package/core/server/framework.ts +43 -0
- package/core/server/index.ts +11 -1
- package/core/server/live/ComponentRegistry.ts +1017 -0
- package/core/server/live/FileUploadManager.ts +272 -0
- package/core/server/live/LiveComponentPerformanceMonitor.ts +930 -0
- package/core/server/live/SingleConnectionManager.ts +0 -0
- package/core/server/live/StateSignature.ts +644 -0
- package/core/server/live/WebSocketConnectionManager.ts +688 -0
- package/core/server/live/websocket-plugin.ts +435 -0
- package/core/server/middleware/errorHandling.ts +141 -0
- package/core/server/middleware/index.ts +16 -0
- package/core/server/plugins/static-files-plugin.ts +232 -0
- package/core/server/services/BaseService.ts +95 -0
- package/core/server/services/ServiceContainer.ts +144 -0
- package/core/server/services/index.ts +9 -0
- package/core/templates/create-project.ts +46 -2
- package/core/testing/index.ts +10 -0
- package/core/testing/setup.ts +74 -0
- package/core/types/build.ts +38 -14
- package/core/types/types.ts +319 -0
- package/core/utils/env-runtime.ts +7 -0
- package/core/utils/errors/handlers.ts +264 -39
- package/core/utils/errors/index.ts +528 -18
- package/core/utils/errors/middleware.ts +114 -0
- package/core/utils/logger/formatters.ts +222 -0
- package/core/utils/logger/index.ts +167 -48
- package/core/utils/logger/middleware.ts +253 -0
- package/core/utils/logger/performance.ts +384 -0
- package/core/utils/logger/transports.ts +365 -0
- package/create-fluxstack.ts +296 -296
- package/fluxstack.config.ts +17 -1
- package/package-template.json +66 -66
- package/package.json +31 -6
- package/public/README.md +16 -0
- package/vite.config.ts +29 -14
- package/.claude/settings.local.json +0 -74
- package/.github/workflows/ci-build-tests.yml +0 -480
- package/.github/workflows/dependency-management.yml +0 -324
- package/.github/workflows/release-validation.yml +0 -355
- package/.kiro/specs/fluxstack-architecture-optimization/design.md +0 -700
- package/.kiro/specs/fluxstack-architecture-optimization/requirements.md +0 -127
- package/.kiro/specs/fluxstack-architecture-optimization/tasks.md +0 -330
- package/CLAUDE.md +0 -200
- package/Dockerfile +0 -58
- package/Dockerfile.backend +0 -52
- package/Dockerfile.frontend +0 -54
- package/README-Docker.md +0 -85
- package/ai-context/00-QUICK-START.md +0 -86
- package/ai-context/README.md +0 -88
- package/ai-context/development/eden-treaty-guide.md +0 -362
- package/ai-context/development/patterns.md +0 -382
- package/ai-context/development/plugins-guide.md +0 -572
- package/ai-context/examples/crud-complete.md +0 -626
- package/ai-context/project/architecture.md +0 -399
- package/ai-context/project/overview.md +0 -213
- package/ai-context/recent-changes/eden-treaty-refactor.md +0 -281
- package/ai-context/recent-changes/type-inference-fix.md +0 -223
- package/ai-context/reference/environment-vars.md +0 -384
- package/ai-context/reference/troubleshooting.md +0 -407
- package/app/client/src/components/TestPage.tsx +0 -453
- package/bun.lock +0 -1063
- package/bunfig.toml +0 -16
- package/core/__tests__/integration.test.ts +0 -227
- package/core/build/index.ts +0 -186
- package/core/config/__tests__/config-loader.test.ts +0 -554
- package/core/config/__tests__/config-merger.test.ts +0 -657
- package/core/config/__tests__/env-converter.test.ts +0 -372
- package/core/config/__tests__/env-processor.test.ts +0 -431
- package/core/config/__tests__/env.test.ts +0 -452
- package/core/config/__tests__/integration.test.ts +0 -418
- package/core/config/__tests__/loader.test.ts +0 -331
- package/core/config/__tests__/schema.test.ts +0 -129
- package/core/config/__tests__/validator.test.ts +0 -318
- package/core/framework/__tests__/server.test.ts +0 -233
- package/core/plugins/__tests__/built-in.test.ts.disabled +0 -366
- package/core/plugins/__tests__/manager.test.ts +0 -398
- package/core/plugins/__tests__/monitoring.test.ts +0 -401
- package/core/plugins/__tests__/registry.test.ts +0 -335
- package/core/utils/__tests__/errors.test.ts +0 -139
- package/core/utils/__tests__/helpers.test.ts +0 -297
- package/core/utils/__tests__/logger.test.ts +0 -141
- package/create-test-app.ts +0 -156
- package/docker-compose.microservices.yml +0 -75
- package/docker-compose.simple.yml +0 -57
- package/docker-compose.yml +0 -71
- package/eslint.config.js +0 -23
- package/flux-cli.ts +0 -214
- package/nginx-lb.conf +0 -37
- package/publish.sh +0 -63
- package/run-clean.ts +0 -26
- package/run-env-tests.ts +0 -313
- package/tailwind.config.js +0 -34
- package/tests/__mocks__/api.ts +0 -56
- package/tests/fixtures/users.ts +0 -69
- package/tests/integration/api/users.routes.test.ts +0 -221
- package/tests/setup.ts +0 -29
- package/tests/unit/app/client/App-simple.test.tsx +0 -56
- package/tests/unit/app/client/App.test.tsx.skip +0 -237
- package/tests/unit/app/client/eden-api.test.ts +0 -186
- package/tests/unit/app/client/simple.test.tsx +0 -23
- package/tests/unit/app/controllers/users.controller.test.ts +0 -150
- package/tests/unit/core/create-project.test.ts.skip +0 -95
- package/tests/unit/core/framework.test.ts +0 -144
- package/tests/unit/core/plugins/logger.test.ts.skip +0 -268
- package/tests/unit/core/plugins/vite.test.ts.disabled +0 -188
- package/tests/utils/test-helpers.ts +0 -61
- package/vitest.config.ts +0 -50
- package/workspace.json +0 -6
package/app/client/src/App.tsx
CHANGED
|
@@ -1,8 +1,24 @@
|
|
|
1
1
|
import { useState, useEffect } from 'react'
|
|
2
2
|
import { api, getErrorMessage } from './lib/eden-api'
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
import {
|
|
4
|
+
FaRocket, FaReact, FaLink, FaDocker, FaFlask, FaPalette,
|
|
5
|
+
FaCheckCircle, FaTimesCircle, FaSpinner, FaSync,
|
|
6
|
+
FaUsers, FaTrash, FaPlus, FaBook, FaCode, FaCog,
|
|
7
|
+
FaServer, FaDatabase, FaShieldAlt, FaBolt, FaLock,
|
|
8
|
+
FaBullseye, FaGlobe, FaFileAlt,
|
|
9
|
+
FaClipboardList, FaFire, FaFlask as FaTest,
|
|
10
|
+
} from 'react-icons/fa'
|
|
11
|
+
import { BrowserRouter, Routes, Route, Link } from 'react-router-dom'
|
|
12
|
+
|
|
13
|
+
// Import page components
|
|
14
|
+
import { OverviewPage } from './pages/Overview'
|
|
15
|
+
import { DemoPage } from './pages/Demo'
|
|
16
|
+
import { HybridLivePage } from './pages/HybridLive'
|
|
17
|
+
import { ApiDocsPage } from './pages/ApiDocs'
|
|
18
|
+
import { MainLayout } from './components/MainLayout'
|
|
19
|
+
import { LiveClock } from './components/LiveClock'
|
|
20
|
+
|
|
21
|
+
// State management is now handled by Zustand stores directly
|
|
6
22
|
|
|
7
23
|
interface User {
|
|
8
24
|
id: number
|
|
@@ -11,8 +27,7 @@ interface User {
|
|
|
11
27
|
createdAt: string
|
|
12
28
|
}
|
|
13
29
|
|
|
14
|
-
function
|
|
15
|
-
const [activeTab, setActiveTab] = useState<TabType>('overview')
|
|
30
|
+
function AppContent() {
|
|
16
31
|
const [users, setUsers] = useState<User[]>([])
|
|
17
32
|
const [loading, setLoading] = useState(false)
|
|
18
33
|
const [apiStatus, setApiStatus] = useState<'online' | 'offline'>('offline')
|
|
@@ -49,7 +64,6 @@ function App() {
|
|
|
49
64
|
return
|
|
50
65
|
}
|
|
51
66
|
|
|
52
|
-
// β¨ Eden Treaty infere automaticamente que data.users Γ© User[]
|
|
53
67
|
setUsers(data.users || [])
|
|
54
68
|
} catch (error) {
|
|
55
69
|
showMessage('error', getErrorMessage(error))
|
|
@@ -74,7 +88,6 @@ function App() {
|
|
|
74
88
|
return
|
|
75
89
|
}
|
|
76
90
|
|
|
77
|
-
// β¨ Eden Treaty infere que result Γ© UserResponse
|
|
78
91
|
if (result.success && result.user) {
|
|
79
92
|
setUsers(prev => [...prev, result.user])
|
|
80
93
|
setName('')
|
|
@@ -94,7 +107,6 @@ function App() {
|
|
|
94
107
|
if (!confirm(`Tem certeza que deseja remover ${userName}?`)) return
|
|
95
108
|
|
|
96
109
|
try {
|
|
97
|
-
// β¨ Chamar API de delete via Eden Treaty nativo
|
|
98
110
|
const { data: result, error } = await api.users({ id: userId }).delete()
|
|
99
111
|
|
|
100
112
|
if (error) {
|
|
@@ -102,9 +114,7 @@ function App() {
|
|
|
102
114
|
return
|
|
103
115
|
}
|
|
104
116
|
|
|
105
|
-
// β¨ Eden Treaty infere que result Γ© UserResponse
|
|
106
117
|
if (result.success) {
|
|
107
|
-
// Remover da lista local apΓ³s sucesso da API
|
|
108
118
|
setUsers(prev => prev.filter(user => user.id !== userId))
|
|
109
119
|
showMessage('success', `UsuΓ‘rio ${userName} removido com sucesso!`)
|
|
110
120
|
} else {
|
|
@@ -124,525 +134,141 @@ function App() {
|
|
|
124
134
|
return name.split(' ').map(n => n[0]).join('').toUpperCase().slice(0, 2)
|
|
125
135
|
}
|
|
126
136
|
|
|
127
|
-
|
|
128
|
-
<div
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
<
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
<
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
</span>
|
|
153
|
-
</div>
|
|
154
|
-
</div>
|
|
155
|
-
</div>
|
|
156
|
-
</div>
|
|
157
|
-
|
|
158
|
-
{/* Features Grid */}
|
|
159
|
-
<div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-6 mb-12">
|
|
160
|
-
{[
|
|
161
|
-
{
|
|
162
|
-
icon: "π",
|
|
163
|
-
title: "Elysia.js",
|
|
164
|
-
description: "Backend rΓ‘pido e type-safe com Bun runtime",
|
|
165
|
-
color: "from-blue-500 to-cyan-500"
|
|
166
|
-
},
|
|
167
|
-
{
|
|
168
|
-
icon: "βοΈ",
|
|
169
|
-
title: "React + Vite",
|
|
170
|
-
description: "Frontend moderno com hot-reload ultrarrΓ‘pido",
|
|
171
|
-
color: "from-purple-500 to-pink-500"
|
|
172
|
-
},
|
|
173
|
-
{
|
|
174
|
-
icon: "π",
|
|
175
|
-
title: "Eden Treaty",
|
|
176
|
-
description: "API type-safe com inferΓͺncia automΓ‘tica de tipos",
|
|
177
|
-
color: "from-emerald-500 to-teal-500"
|
|
178
|
-
},
|
|
179
|
-
{
|
|
180
|
-
icon: "π³",
|
|
181
|
-
title: "Docker Ready",
|
|
182
|
-
description: "Deploy fΓ‘cil com configuraΓ§Γ΅es otimizadas",
|
|
183
|
-
color: "from-indigo-500 to-purple-500"
|
|
184
|
-
},
|
|
185
|
-
{
|
|
186
|
-
icon: "π§ͺ",
|
|
187
|
-
title: "Testing",
|
|
188
|
-
description: "Vitest + Testing Library configurados",
|
|
189
|
-
color: "from-orange-500 to-red-500"
|
|
190
|
-
},
|
|
191
|
-
{
|
|
192
|
-
icon: "π¨",
|
|
193
|
-
title: "Tailwind CSS 4",
|
|
194
|
-
description: "Styling moderno e responsivo",
|
|
195
|
-
color: "from-teal-500 to-green-500"
|
|
196
|
-
}
|
|
197
|
-
].map((feature, index) => (
|
|
198
|
-
<div
|
|
199
|
-
key={index}
|
|
200
|
-
className="group relative bg-white rounded-2xl p-6 shadow-lg hover:shadow-xl transition-all duration-300 hover:-translate-y-1 border border-gray-200"
|
|
201
|
-
>
|
|
202
|
-
<div className={`absolute inset-0 bg-gradient-to-r ${feature.color} opacity-0 group-hover:opacity-5 rounded-2xl transition-opacity duration-300`}></div>
|
|
203
|
-
<div className="relative">
|
|
204
|
-
<div className="text-4xl mb-4">{feature.icon}</div>
|
|
205
|
-
<h3 className="text-xl font-semibold text-gray-900 mb-2">{feature.title}</h3>
|
|
206
|
-
<p className="text-gray-600 leading-relaxed">{feature.description}</p>
|
|
207
|
-
</div>
|
|
208
|
-
</div>
|
|
209
|
-
))}
|
|
210
|
-
</div>
|
|
211
|
-
|
|
212
|
-
{/* Tech Stack Section */}
|
|
213
|
-
<div className="bg-white rounded-2xl shadow-lg border border-gray-200 overflow-hidden">
|
|
214
|
-
<div className="bg-gradient-to-r from-gray-50 to-slate-100 px-8 py-6 border-b border-gray-200">
|
|
215
|
-
<h2 className="text-2xl font-bold text-gray-900 text-center">Stack TecnolΓ³gica</h2>
|
|
216
|
-
</div>
|
|
217
|
-
<div className="p-8">
|
|
218
|
-
<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
|
|
219
|
-
{[
|
|
220
|
-
{
|
|
221
|
-
title: "Backend",
|
|
222
|
-
color: "blue",
|
|
223
|
-
items: [
|
|
224
|
-
"Elysia.js - Web framework",
|
|
225
|
-
"Bun - Runtime & package manager",
|
|
226
|
-
"TypeScript - Type safety"
|
|
227
|
-
]
|
|
228
|
-
},
|
|
229
|
-
{
|
|
230
|
-
title: "Frontend",
|
|
231
|
-
color: "purple",
|
|
232
|
-
items: [
|
|
233
|
-
"React 19 - UI library",
|
|
234
|
-
"Vite - Build tool",
|
|
235
|
-
"Tailwind CSS 4 - Styling"
|
|
236
|
-
]
|
|
237
|
-
},
|
|
238
|
-
{
|
|
239
|
-
title: "ComunicaΓ§Γ£o",
|
|
240
|
-
color: "emerald",
|
|
241
|
-
items: [
|
|
242
|
-
"Eden Treaty - Type-safe API",
|
|
243
|
-
"End-to-end TypeScript",
|
|
244
|
-
"Automatic type inference"
|
|
245
|
-
]
|
|
246
|
-
}
|
|
247
|
-
].map((category, index) => (
|
|
248
|
-
<div key={index} className="space-y-4">
|
|
249
|
-
<h3 className={`text-lg font-semibold text-${category.color}-600 pb-2 border-b-2 border-${category.color}-100`}>
|
|
250
|
-
{category.title}
|
|
251
|
-
</h3>
|
|
252
|
-
<ul className="space-y-3">
|
|
253
|
-
{category.items.map((item, itemIndex) => (
|
|
254
|
-
<li key={itemIndex} className="flex items-start gap-3 text-gray-600">
|
|
255
|
-
<div className={`w-2 h-2 rounded-full bg-${category.color}-400 flex-shrink-0 mt-2`}></div>
|
|
256
|
-
<span>{item}</span>
|
|
257
|
-
</li>
|
|
258
|
-
))}
|
|
259
|
-
</ul>
|
|
260
|
-
</div>
|
|
261
|
-
))}
|
|
262
|
-
</div>
|
|
263
|
-
</div>
|
|
264
|
-
</div>
|
|
265
|
-
</div>
|
|
266
|
-
)
|
|
267
|
-
|
|
268
|
-
const renderDemo = () => (
|
|
269
|
-
<div className="space-y-8">
|
|
270
|
-
{/* Header */}
|
|
271
|
-
<div className="text-center">
|
|
272
|
-
<h2 className="text-3xl font-bold text-gray-900 mb-4">π₯ Demo Interativo</h2>
|
|
273
|
-
<p className="text-lg text-gray-600 max-w-2xl mx-auto">
|
|
274
|
-
Teste a API em tempo real com hot reload coordenado e Eden Treaty π
|
|
275
|
-
</p>
|
|
276
|
-
</div>
|
|
277
|
-
|
|
278
|
-
{/* Stats Cards */}
|
|
279
|
-
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
|
280
|
-
<div className="bg-gradient-to-br from-blue-50 to-blue-100 border border-blue-200 rounded-2xl p-6 text-center">
|
|
281
|
-
<div className="text-4xl font-bold text-blue-600 mb-2">{users.length}</div>
|
|
282
|
-
<div className="text-sm font-medium text-blue-700 uppercase tracking-wide">UsuΓ‘rios</div>
|
|
283
|
-
</div>
|
|
284
|
-
<div className={`bg-gradient-to-br ${apiStatus === 'online' ? 'from-emerald-50 to-emerald-100 border-emerald-200' : 'from-red-50 to-red-100 border-red-200'} border rounded-2xl p-6 text-center`}>
|
|
285
|
-
<div className="text-4xl mb-2">{apiStatus === 'online' ? 'β
' : 'β'}</div>
|
|
286
|
-
<div className={`text-sm font-medium uppercase tracking-wide ${apiStatus === 'online' ? 'text-emerald-700' : 'text-red-700'}`}>
|
|
287
|
-
API {apiStatus === 'online' ? 'Online' : 'Offline'}
|
|
288
|
-
</div>
|
|
289
|
-
</div>
|
|
290
|
-
<div className="bg-gradient-to-br from-purple-50 to-purple-100 border border-purple-200 rounded-2xl p-6 text-center">
|
|
291
|
-
<div className="text-4xl mb-2">π</div>
|
|
292
|
-
<div className="text-sm font-medium text-purple-700 uppercase tracking-wide">Eden Treaty</div>
|
|
293
|
-
</div>
|
|
294
|
-
</div>
|
|
295
|
-
|
|
296
|
-
{/* Add User Form */}
|
|
297
|
-
<div className="bg-white rounded-2xl shadow-lg border border-gray-200 overflow-hidden">
|
|
298
|
-
<div className="bg-gradient-to-r from-gray-50 to-slate-100 px-6 py-4 border-b border-gray-200">
|
|
299
|
-
<h3 className="text-lg font-semibold text-gray-900">Adicionar UsuΓ‘rio</h3>
|
|
300
|
-
</div>
|
|
301
|
-
<div className="p-6">
|
|
302
|
-
<form onSubmit={handleSubmit} className="grid grid-cols-1 md:grid-cols-2 gap-4 md:gap-6">
|
|
303
|
-
<div className="space-y-2">
|
|
304
|
-
<label className="block text-sm font-medium text-gray-700">Nome</label>
|
|
305
|
-
<input
|
|
306
|
-
type="text"
|
|
307
|
-
className="w-full px-4 py-3 border border-gray-300 rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all duration-200 placeholder-gray-400"
|
|
308
|
-
value={name}
|
|
309
|
-
onChange={(e) => setName(e.target.value)}
|
|
310
|
-
placeholder="Nome completo"
|
|
311
|
-
required
|
|
312
|
-
/>
|
|
313
|
-
</div>
|
|
314
|
-
<div className="space-y-2">
|
|
315
|
-
<label className="block text-sm font-medium text-gray-700">Email</label>
|
|
316
|
-
<input
|
|
317
|
-
type="email"
|
|
318
|
-
className="w-full px-4 py-3 border border-gray-300 rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all duration-200 placeholder-gray-400"
|
|
319
|
-
value={email}
|
|
320
|
-
onChange={(e) => setEmail(e.target.value)}
|
|
321
|
-
placeholder="email@exemplo.com"
|
|
322
|
-
required
|
|
323
|
-
/>
|
|
324
|
-
</div>
|
|
325
|
-
<div className="md:col-span-2">
|
|
326
|
-
<button
|
|
327
|
-
type="submit"
|
|
328
|
-
className="w-full md:w-auto px-8 py-3 bg-gradient-to-r from-blue-600 to-blue-700 text-white font-medium rounded-xl hover:from-blue-700 hover:to-blue-800 focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed transition-all duration-200 shadow-lg hover:shadow-xl"
|
|
329
|
-
disabled={submitting || !name.trim() || !email.trim()}
|
|
330
|
-
>
|
|
331
|
-
{submitting ? (
|
|
332
|
-
<span className="flex items-center gap-2">
|
|
333
|
-
<div className="w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin"></div>
|
|
334
|
-
Adicionando...
|
|
335
|
-
</span>
|
|
336
|
-
) : (
|
|
337
|
-
'Adicionar UsuΓ‘rio'
|
|
338
|
-
)}
|
|
339
|
-
</button>
|
|
340
|
-
</div>
|
|
341
|
-
</form>
|
|
342
|
-
</div>
|
|
343
|
-
</div>
|
|
344
|
-
|
|
345
|
-
{/* Users List */}
|
|
346
|
-
<div className="bg-white rounded-2xl shadow-lg border border-gray-200 overflow-hidden">
|
|
347
|
-
<div className="bg-gradient-to-r from-gray-50 to-slate-100 px-6 py-4 border-b border-gray-200 flex justify-between items-center">
|
|
348
|
-
<h3 className="text-lg font-semibold text-gray-900">UsuΓ‘rios ({users.length})</h3>
|
|
349
|
-
<button
|
|
350
|
-
className="flex items-center gap-2 px-4 py-2 bg-white border border-gray-300 rounded-lg hover:bg-gray-50 focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 disabled:opacity-50 transition-all duration-200"
|
|
351
|
-
onClick={loadUsers}
|
|
352
|
-
disabled={loading}
|
|
353
|
-
>
|
|
354
|
-
{loading ? (
|
|
355
|
-
<div className="w-4 h-4 border-2 border-gray-400 border-t-transparent rounded-full animate-spin"></div>
|
|
356
|
-
) : (
|
|
357
|
-
<span className="text-lg">β»</span>
|
|
358
|
-
)}
|
|
359
|
-
Atualizar
|
|
360
|
-
</button>
|
|
361
|
-
</div>
|
|
362
|
-
|
|
363
|
-
<div className="p-6">
|
|
364
|
-
{loading ? (
|
|
365
|
-
<div className="text-center py-12">
|
|
366
|
-
<div className="w-8 h-8 border-4 border-blue-200 border-t-blue-600 rounded-full animate-spin mx-auto mb-4"></div>
|
|
367
|
-
<p className="text-gray-600">Carregando usuΓ‘rios...</p>
|
|
368
|
-
</div>
|
|
369
|
-
) : users.length === 0 ? (
|
|
370
|
-
<div className="text-center py-12">
|
|
371
|
-
<div className="text-6xl mb-4 opacity-50">π₯</div>
|
|
372
|
-
<h4 className="text-lg font-medium text-gray-900 mb-2">Nenhum usuΓ‘rio encontrado</h4>
|
|
373
|
-
<p className="text-gray-600">Adicione o primeiro usuΓ‘rio usando o formulΓ‘rio acima</p>
|
|
374
|
-
</div>
|
|
375
|
-
) : (
|
|
376
|
-
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
|
377
|
-
{users.map(user => (
|
|
378
|
-
<div key={user.id} className="group bg-gray-50 border border-gray-200 rounded-xl p-4 hover:shadow-lg hover:border-blue-300 transition-all duration-200">
|
|
379
|
-
<div className="flex items-start gap-3">
|
|
380
|
-
<div className="w-12 h-12 bg-gradient-to-br from-blue-500 to-purple-600 rounded-full flex items-center justify-center text-white font-bold text-sm flex-shrink-0">
|
|
381
|
-
{getInitials(user.name)}
|
|
382
|
-
</div>
|
|
383
|
-
<div className="flex-1 min-w-0">
|
|
384
|
-
<h4 className="font-medium text-gray-900 truncate">{user.name}</h4>
|
|
385
|
-
<p className="text-sm text-gray-600 truncate">{user.email}</p>
|
|
386
|
-
<button
|
|
387
|
-
className="mt-3 w-full px-3 py-2 bg-red-50 text-red-700 border border-red-200 rounded-lg hover:bg-red-100 hover:border-red-300 focus:ring-2 focus:ring-red-500 focus:ring-offset-2 transition-all duration-200 text-sm font-medium"
|
|
388
|
-
onClick={() => handleDelete(user.id, user.name)}
|
|
389
|
-
>
|
|
390
|
-
Remover
|
|
391
|
-
</button>
|
|
137
|
+
return (
|
|
138
|
+
<div>
|
|
139
|
+
<Routes>
|
|
140
|
+
{/* Full-screen Live App Route */}
|
|
141
|
+
<Route path="/live-app" element={<MainLayout />} />
|
|
142
|
+
|
|
143
|
+
{/* Regular routes with header and layout */}
|
|
144
|
+
<Route path="*" element={
|
|
145
|
+
<div className="min-h-screen bg-gradient-to-br from-slate-50 via-blue-50 to-indigo-100">
|
|
146
|
+
{/* Header */}
|
|
147
|
+
<header className="bg-white/80 backdrop-blur-sm border-b border-gray-200 sticky top-0 z-50">
|
|
148
|
+
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
149
|
+
<div className="flex justify-between items-center h-16">
|
|
150
|
+
{/* Logo and Navigation */}
|
|
151
|
+
<div className="flex items-center space-x-8">
|
|
152
|
+
<div className="flex items-center space-x-3">
|
|
153
|
+
<div className="flex items-center gap-2">
|
|
154
|
+
<FaFire className="text-2xl text-orange-500" />
|
|
155
|
+
<div className="text-2xl font-bold bg-gradient-to-r from-blue-600 via-purple-600 to-indigo-600 bg-clip-text text-transparent">
|
|
156
|
+
FluxStack
|
|
157
|
+
</div>
|
|
158
|
+
</div>
|
|
159
|
+
<span className="px-2 py-1 text-xs font-medium bg-blue-100 text-blue-800 rounded-full">
|
|
160
|
+
v1.4.0
|
|
161
|
+
</span>
|
|
392
162
|
</div>
|
|
163
|
+
|
|
164
|
+
{/* Navigation Tabs */}
|
|
165
|
+
<nav className="hidden md:flex space-x-1">
|
|
166
|
+
{[
|
|
167
|
+
{ id: 'overview', label: 'VisΓ£o Geral', icon: <FaClipboardList />, path: '/' },
|
|
168
|
+
{ id: 'demo', label: 'Demo', icon: <FaRocket />, path: '/demo' },
|
|
169
|
+
{ id: 'hybrid-live', label: 'Hybrid Live', icon: <FaBolt />, path: '/hybrid-live' },
|
|
170
|
+
{ id: 'live-app', label: 'Live App', icon: <FaFire />, path: '/live-app' },
|
|
171
|
+
{ id: 'api-docs', label: 'API Docs', icon: <FaBook />, path: '/api-docs' },
|
|
172
|
+
{ id: 'tests', label: 'Testes', icon: <FaTest />, path: '/tests' }
|
|
173
|
+
].map(tab => (
|
|
174
|
+
<Link
|
|
175
|
+
key={tab.id}
|
|
176
|
+
to={tab.path}
|
|
177
|
+
className={`px-4 py-2 text-sm font-medium rounded-lg transition-all duration-200 ${
|
|
178
|
+
location.pathname === tab.path
|
|
179
|
+
? 'bg-blue-100 text-blue-700 shadow-sm'
|
|
180
|
+
: 'text-gray-600 hover:text-gray-900 hover:bg-gray-100'
|
|
181
|
+
}`}
|
|
182
|
+
>
|
|
183
|
+
<div className="flex items-center gap-2">
|
|
184
|
+
{tab.icon}
|
|
185
|
+
{tab.label}
|
|
186
|
+
</div>
|
|
187
|
+
</Link>
|
|
188
|
+
))}
|
|
189
|
+
</nav>
|
|
393
190
|
</div>
|
|
394
|
-
</div>
|
|
395
|
-
))}
|
|
396
|
-
</div>
|
|
397
|
-
)}
|
|
398
|
-
</div>
|
|
399
|
-
</div>
|
|
400
|
-
</div>
|
|
401
|
-
)
|
|
402
191
|
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
415
|
-
<div className="group bg-white rounded-2xl p-6 shadow-lg border border-gray-200 hover:shadow-xl hover:border-blue-300 transition-all duration-300">
|
|
416
|
-
<div className="text-center">
|
|
417
|
-
<div className="text-4xl mb-4">π</div>
|
|
418
|
-
<h3 className="text-xl font-semibold text-gray-900 mb-2">Swagger UI Interativo</h3>
|
|
419
|
-
<p className="text-gray-600 mb-6">Interface completa para testar todos os endpoints da API</p>
|
|
420
|
-
<a
|
|
421
|
-
href="/swagger"
|
|
422
|
-
target="_blank"
|
|
423
|
-
rel="noopener noreferrer"
|
|
424
|
-
className="inline-flex items-center gap-2 px-6 py-3 bg-gradient-to-r from-blue-600 to-blue-700 text-white font-medium rounded-xl hover:from-blue-700 hover:to-blue-800 focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 transition-all duration-200 shadow-lg hover:shadow-xl"
|
|
425
|
-
>
|
|
426
|
-
π Abrir em Nova Aba
|
|
427
|
-
</a>
|
|
428
|
-
</div>
|
|
429
|
-
</div>
|
|
430
|
-
|
|
431
|
-
<div className="group bg-white rounded-2xl p-6 shadow-lg border border-gray-200 hover:shadow-xl hover:border-purple-300 transition-all duration-300">
|
|
432
|
-
<div className="text-center">
|
|
433
|
-
<div className="text-4xl mb-4">π</div>
|
|
434
|
-
<h3 className="text-xl font-semibold text-gray-900 mb-2">OpenAPI Spec (JSON)</h3>
|
|
435
|
-
<p className="text-gray-600 mb-6">EspecificaΓ§Γ£o OpenAPI em formato JSON para integraΓ§Γ£o</p>
|
|
436
|
-
<a
|
|
437
|
-
href="/swagger/json"
|
|
438
|
-
target="_blank"
|
|
439
|
-
rel="noopener noreferrer"
|
|
440
|
-
className="inline-flex items-center gap-2 px-6 py-3 bg-gradient-to-r from-purple-600 to-purple-700 text-white font-medium rounded-xl hover:from-purple-700 hover:to-purple-800 focus:ring-2 focus:ring-purple-500 focus:ring-offset-2 transition-all duration-200 shadow-lg hover:shadow-xl"
|
|
441
|
-
>
|
|
442
|
-
π Ver JSON
|
|
443
|
-
</a>
|
|
444
|
-
</div>
|
|
445
|
-
</div>
|
|
446
|
-
</div>
|
|
447
|
-
|
|
448
|
-
{/* Embedded Swagger */}
|
|
449
|
-
<div className="bg-white rounded-2xl shadow-lg border border-gray-200 overflow-hidden">
|
|
450
|
-
<div className="bg-gradient-to-r from-gray-50 to-slate-100 px-6 py-4 border-b border-gray-200">
|
|
451
|
-
<h3 className="text-lg font-semibold text-gray-900">π§ DocumentaΓ§Γ£o Integrada</h3>
|
|
452
|
-
</div>
|
|
453
|
-
<iframe
|
|
454
|
-
src="/swagger"
|
|
455
|
-
className="w-full h-[600px] border-0"
|
|
456
|
-
title="Swagger UI"
|
|
457
|
-
/>
|
|
458
|
-
</div>
|
|
459
|
-
|
|
460
|
-
{/* Eden Treaty Guide */}
|
|
461
|
-
<div className="bg-white rounded-2xl shadow-lg border border-gray-200 overflow-hidden">
|
|
462
|
-
<div className="bg-gradient-to-r from-gray-50 to-slate-100 px-6 py-4 border-b border-gray-200">
|
|
463
|
-
<h3 className="text-lg font-semibold text-gray-900">π§ Como usar Eden Treaty</h3>
|
|
464
|
-
</div>
|
|
465
|
-
<div className="p-6 space-y-6">
|
|
466
|
-
<div>
|
|
467
|
-
<h4 className="text-base font-semibold text-gray-900 mb-3">ConfiguraΓ§Γ£o do Cliente:</h4>
|
|
468
|
-
<pre className="bg-gray-900 text-gray-100 p-4 rounded-xl overflow-x-auto text-sm border border-gray-700">
|
|
469
|
-
{`import { treaty } from '@elysiajs/eden'
|
|
470
|
-
import type { App } from './server'
|
|
471
|
-
|
|
472
|
-
const client = treaty<App>('http://localhost:3000')
|
|
473
|
-
export const api = client.api`}
|
|
474
|
-
</pre>
|
|
475
|
-
</div>
|
|
476
|
-
|
|
477
|
-
<div>
|
|
478
|
-
<h4 className="text-base font-semibold text-gray-900 mb-3">Exemplos de Uso:</h4>
|
|
479
|
-
<pre className="bg-gray-900 text-gray-100 p-4 rounded-xl overflow-x-auto text-sm border border-gray-700">
|
|
480
|
-
{`// Listar usuΓ‘rios
|
|
481
|
-
const users = await api.users.get()
|
|
482
|
-
|
|
483
|
-
// Criar usuΓ‘rio
|
|
484
|
-
const newUser = await api.users.post({
|
|
485
|
-
name: "JoΓ£o Silva",
|
|
486
|
-
email: "joao@example.com"
|
|
487
|
-
})
|
|
488
|
-
|
|
489
|
-
// Deletar usuΓ‘rio
|
|
490
|
-
await api.users["1"].delete()
|
|
491
|
-
|
|
492
|
-
// Health check
|
|
493
|
-
const health = await api.health.get()`}
|
|
494
|
-
</pre>
|
|
495
|
-
</div>
|
|
496
|
-
|
|
497
|
-
<div>
|
|
498
|
-
<h4 className="text-base font-semibold text-gray-900 mb-3">Com tratamento de erros:</h4>
|
|
499
|
-
<pre className="bg-gray-900 text-gray-100 p-4 rounded-xl overflow-x-auto text-sm border border-gray-700">
|
|
500
|
-
{`try {
|
|
501
|
-
const result = await apiCall(api.users.post({
|
|
502
|
-
name: "Maria Silva",
|
|
503
|
-
email: "maria@example.com"
|
|
504
|
-
}))
|
|
505
|
-
|
|
506
|
-
if (result.success) {
|
|
507
|
-
console.log('UsuΓ‘rio criado:', result.user)
|
|
508
|
-
}
|
|
509
|
-
} catch (error) {
|
|
510
|
-
console.error('Erro:', getErrorMessage(error))
|
|
511
|
-
}`}
|
|
512
|
-
</pre>
|
|
513
|
-
</div>
|
|
514
|
-
</div>
|
|
515
|
-
</div>
|
|
516
|
-
|
|
517
|
-
{/* Features */}
|
|
518
|
-
<div className="bg-white rounded-2xl shadow-lg border border-gray-200 overflow-hidden">
|
|
519
|
-
<div className="bg-gradient-to-r from-gray-50 to-slate-100 px-6 py-4 border-b border-gray-200">
|
|
520
|
-
<h3 className="text-lg font-semibold text-gray-900 text-center">β¨ Funcionalidades</h3>
|
|
521
|
-
</div>
|
|
522
|
-
<div className="p-6">
|
|
523
|
-
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
524
|
-
{[
|
|
525
|
-
{
|
|
526
|
-
icon: "π",
|
|
527
|
-
title: "Type Safety",
|
|
528
|
-
description: "Tipos TypeScript inferidos automaticamente"
|
|
529
|
-
},
|
|
530
|
-
{
|
|
531
|
-
icon: "β‘",
|
|
532
|
-
title: "Auto-complete",
|
|
533
|
-
description: "IntelliSense completo no editor"
|
|
534
|
-
},
|
|
535
|
-
{
|
|
536
|
-
icon: "π",
|
|
537
|
-
title: "SincronizaΓ§Γ£o",
|
|
538
|
-
description: "MudanΓ§as no backend refletem automaticamente no frontend"
|
|
539
|
-
},
|
|
540
|
-
{
|
|
541
|
-
icon: "π",
|
|
542
|
-
title: "Debugging",
|
|
543
|
-
description: "Erros de tipo detectados em tempo de compilaΓ§Γ£o"
|
|
544
|
-
}
|
|
545
|
-
].map((feature, index) => (
|
|
546
|
-
<div key={index} className="flex items-start gap-4 p-4 rounded-xl bg-gray-50 hover:bg-gray-100 transition-colors duration-200">
|
|
547
|
-
<div className="text-2xl">{feature.icon}</div>
|
|
548
|
-
<div>
|
|
549
|
-
<h4 className="font-semibold text-gray-900 mb-1">{feature.title}</h4>
|
|
550
|
-
<p className="text-gray-600 text-sm">{feature.description}</p>
|
|
192
|
+
{/* Status Badge */}
|
|
193
|
+
<div className={`flex items-center space-x-2 px-3 py-2 rounded-full text-sm font-medium ${
|
|
194
|
+
apiStatus === 'online'
|
|
195
|
+
? 'bg-emerald-100 text-emerald-700'
|
|
196
|
+
: 'bg-red-100 text-red-700'
|
|
197
|
+
}`}>
|
|
198
|
+
<div className={`w-2 h-2 rounded-full ${
|
|
199
|
+
apiStatus === 'online' ? 'bg-emerald-400' : 'bg-red-400'
|
|
200
|
+
}`}></div>
|
|
201
|
+
<span>API {apiStatus === 'online' ? 'Online' : 'Offline'}</span>
|
|
202
|
+
</div>
|
|
551
203
|
</div>
|
|
552
|
-
</div>
|
|
553
|
-
))}
|
|
554
|
-
</div>
|
|
555
|
-
</div>
|
|
556
|
-
</div>
|
|
557
|
-
</div>
|
|
558
|
-
)
|
|
559
204
|
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
205
|
+
{/* Mobile Navigation */}
|
|
206
|
+
<div className="md:hidden pb-3">
|
|
207
|
+
<nav className="flex space-x-1">
|
|
208
|
+
{[
|
|
209
|
+
{ id: 'overview', label: 'VisΓ£o', icon: <FaClipboardList />, path: '/' },
|
|
210
|
+
{ id: 'demo', label: 'Demo', icon: <FaRocket />, path: '/demo' },
|
|
211
|
+
{ id: 'hybrid-live', label: 'Hybrid', icon: <FaBolt />, path: '/hybrid-live' },
|
|
212
|
+
{ id: 'live-app', label: 'Live', icon: <FaFire />, path: '/live-app' },
|
|
213
|
+
{ id: 'api-docs', label: 'Docs', icon: <FaBook />, path: '/api-docs' },
|
|
214
|
+
{ id: 'tests', label: 'Testes', icon: <FaTest />, path: '/tests' }
|
|
215
|
+
].map(tab => (
|
|
216
|
+
<Link
|
|
217
|
+
key={tab.id}
|
|
218
|
+
to={tab.path}
|
|
219
|
+
className={`flex-1 px-3 py-2 text-xs font-medium rounded-lg transition-all duration-200 ${
|
|
220
|
+
location.pathname === tab.path
|
|
221
|
+
? 'bg-blue-100 text-blue-700'
|
|
222
|
+
: 'text-gray-600 hover:text-gray-900 hover:bg-gray-100'
|
|
223
|
+
}`}
|
|
224
|
+
>
|
|
225
|
+
<div className="flex flex-col items-center gap-1">
|
|
226
|
+
{tab.icon}
|
|
227
|
+
<span>{tab.label}</span>
|
|
228
|
+
</div>
|
|
229
|
+
</Link>
|
|
230
|
+
))}
|
|
231
|
+
</nav>
|
|
571
232
|
</div>
|
|
572
|
-
<span className="px-2 py-1 text-xs font-medium bg-blue-100 text-blue-800 rounded-full">
|
|
573
|
-
v1.4.0
|
|
574
|
-
</span>
|
|
575
233
|
</div>
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
</
|
|
611
|
-
</div>
|
|
612
|
-
|
|
613
|
-
{/* Mobile Navigation */}
|
|
614
|
-
<div className="md:hidden pb-3">
|
|
615
|
-
<nav className="flex space-x-1">
|
|
616
|
-
{[
|
|
617
|
-
{ id: 'overview', label: 'π VisΓ£o Geral' },
|
|
618
|
-
{ id: 'demo', label: 'π Demo' },
|
|
619
|
-
{ id: 'api-docs', label: 'π Docs' },
|
|
620
|
-
{ id: 'tests', label: 'π§ͺ Testes' }
|
|
621
|
-
].map(tab => (
|
|
622
|
-
<button
|
|
623
|
-
key={tab.id}
|
|
624
|
-
className={`flex-1 px-3 py-2 text-xs font-medium rounded-lg transition-all duration-200 ${
|
|
625
|
-
activeTab === tab.id
|
|
626
|
-
? 'bg-blue-100 text-blue-700'
|
|
627
|
-
: 'text-gray-600 hover:text-gray-900 hover:bg-gray-100'
|
|
628
|
-
}`}
|
|
629
|
-
onClick={() => setActiveTab(tab.id as TabType)}
|
|
630
|
-
>
|
|
631
|
-
{tab.label}
|
|
632
|
-
</button>
|
|
633
|
-
))}
|
|
634
|
-
</nav>
|
|
234
|
+
</header>
|
|
235
|
+
|
|
236
|
+
{/* Main Content */}
|
|
237
|
+
<main className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
|
238
|
+
<Routes>
|
|
239
|
+
<Route path="/" element={<OverviewPage />} />
|
|
240
|
+
<Route
|
|
241
|
+
path="/demo"
|
|
242
|
+
element={
|
|
243
|
+
<DemoPage
|
|
244
|
+
users={users}
|
|
245
|
+
apiStatus={apiStatus}
|
|
246
|
+
loading={loading}
|
|
247
|
+
submitting={submitting}
|
|
248
|
+
name={name}
|
|
249
|
+
email={email}
|
|
250
|
+
setName={setName}
|
|
251
|
+
setEmail={setEmail}
|
|
252
|
+
handleSubmit={handleSubmit}
|
|
253
|
+
handleDelete={handleDelete}
|
|
254
|
+
loadUsers={loadUsers}
|
|
255
|
+
getInitials={getInitials}
|
|
256
|
+
/>
|
|
257
|
+
}
|
|
258
|
+
/>
|
|
259
|
+
<Route path="/hybrid-live" element={<HybridLivePage />} />
|
|
260
|
+
<Route path="/api-docs" element={<ApiDocsPage />} />
|
|
261
|
+
<Route path="/tests" element={
|
|
262
|
+
<div className="p-6">
|
|
263
|
+
<h2 className="text-2xl font-bold mb-4">π§ͺ Tests</h2>
|
|
264
|
+
<p className="text-gray-600">Test suite functionality will be available here.</p>
|
|
265
|
+
</div>
|
|
266
|
+
} />
|
|
267
|
+
</Routes>
|
|
268
|
+
</main>
|
|
635
269
|
</div>
|
|
636
|
-
|
|
637
|
-
</
|
|
638
|
-
|
|
639
|
-
{/* Main Content */}
|
|
640
|
-
<main className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
|
641
|
-
{activeTab === 'overview' && renderOverview()}
|
|
642
|
-
{activeTab === 'demo' && renderDemo()}
|
|
643
|
-
{activeTab === 'api-docs' && renderApiDocs()}
|
|
644
|
-
{activeTab === 'tests' && <TestPage />}
|
|
645
|
-
</main>
|
|
270
|
+
} />
|
|
271
|
+
</Routes>
|
|
646
272
|
|
|
647
273
|
{/* Toast Notification */}
|
|
648
274
|
{message && (
|
|
@@ -655,9 +281,11 @@ const health = await api.health.get()`}
|
|
|
655
281
|
onClick={() => setMessage(null)}
|
|
656
282
|
>
|
|
657
283
|
<div className="flex items-center space-x-2">
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
284
|
+
{message.type === 'success' ? (
|
|
285
|
+
<FaCheckCircle className="text-lg" />
|
|
286
|
+
) : (
|
|
287
|
+
<FaTimesCircle className="text-lg" />
|
|
288
|
+
)}
|
|
661
289
|
<span className="font-medium">{message.text}</span>
|
|
662
290
|
</div>
|
|
663
291
|
</div>
|
|
@@ -666,4 +294,9 @@ const health = await api.health.get()`}
|
|
|
666
294
|
)
|
|
667
295
|
}
|
|
668
296
|
|
|
297
|
+
// Main App component - Zustand stores are available globally
|
|
298
|
+
function App() {
|
|
299
|
+
return <AppContent />
|
|
300
|
+
}
|
|
301
|
+
|
|
669
302
|
export default App
|