create-fluxstack 1.7.5 → 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 (154) hide show
  1. package/.dockerignore +82 -0
  2. package/.env.example +19 -0
  3. package/Dockerfile +70 -0
  4. package/README.md +6 -3
  5. package/app/client/SIMPLIFICATION.md +140 -0
  6. package/app/client/frontend-only.ts +1 -1
  7. package/app/client/src/App.tsx +148 -283
  8. package/app/client/src/index.css +5 -20
  9. package/app/client/src/lib/eden-api.ts +53 -220
  10. package/app/client/src/main.tsx +2 -3
  11. package/app/server/app.ts +20 -5
  12. package/app/server/backend-only.ts +15 -12
  13. package/app/server/controllers/users.controller.ts +57 -31
  14. package/app/server/index.ts +86 -96
  15. package/app/server/live/register-components.ts +18 -7
  16. package/app/server/routes/env-test.ts +110 -0
  17. package/app/server/routes/index.ts +1 -8
  18. package/app/server/routes/users.routes.ts +192 -91
  19. package/config/app.config.ts +2 -54
  20. package/config/client.config.ts +95 -0
  21. package/config/fluxstack.config.ts +2 -2
  22. package/config/index.ts +57 -22
  23. package/config/monitoring.config.ts +114 -0
  24. package/config/plugins.config.ts +80 -0
  25. package/config/runtime.config.ts +0 -17
  26. package/config/server.config.ts +50 -30
  27. package/core/build/bundler.ts +17 -16
  28. package/core/build/flux-plugins-generator.ts +34 -23
  29. package/core/build/index.ts +32 -31
  30. package/core/build/live-components-generator.ts +44 -30
  31. package/core/build/optimizer.ts +37 -17
  32. package/core/cli/command-registry.ts +4 -14
  33. package/core/cli/commands/plugin-deps.ts +8 -8
  34. package/core/cli/generators/component.ts +3 -3
  35. package/core/cli/generators/controller.ts +4 -4
  36. package/core/cli/generators/index.ts +8 -8
  37. package/core/cli/generators/interactive.ts +4 -4
  38. package/core/cli/generators/plugin.ts +3 -3
  39. package/core/cli/generators/prompts.ts +1 -1
  40. package/core/cli/generators/route.ts +27 -11
  41. package/core/cli/generators/service.ts +5 -5
  42. package/core/cli/generators/template-engine.ts +1 -1
  43. package/core/cli/generators/types.ts +1 -1
  44. package/core/cli/index.ts +158 -189
  45. package/core/cli/plugin-discovery.ts +3 -3
  46. package/core/client/hooks/index.ts +2 -2
  47. package/core/client/hooks/state-validator.ts +1 -1
  48. package/core/client/hooks/useAuth.ts +1 -1
  49. package/core/client/hooks/useChunkedUpload.ts +1 -1
  50. package/core/client/hooks/useHybridLiveComponent.ts +1 -1
  51. package/core/client/hooks/useWebSocket.ts +1 -1
  52. package/core/config/env.ts +5 -1
  53. package/core/config/runtime-config.ts +12 -10
  54. package/core/config/schema.ts +33 -2
  55. package/core/framework/server.ts +30 -14
  56. package/core/framework/types.ts +2 -2
  57. package/core/index.ts +31 -23
  58. package/core/live/ComponentRegistry.ts +1 -1
  59. package/core/plugins/built-in/live-components/commands/create-live-component.ts +1 -1
  60. package/core/plugins/built-in/live-components/index.ts +1 -1
  61. package/core/plugins/built-in/monitoring/index.ts +65 -161
  62. package/core/plugins/built-in/static/index.ts +75 -277
  63. package/core/plugins/built-in/swagger/index.ts +301 -231
  64. package/core/plugins/built-in/vite/index.ts +342 -377
  65. package/core/plugins/config.ts +2 -2
  66. package/core/plugins/dependency-manager.ts +2 -2
  67. package/core/plugins/discovery.ts +1 -1
  68. package/core/plugins/executor.ts +2 -2
  69. package/core/plugins/manager.ts +19 -4
  70. package/core/plugins/module-resolver.ts +1 -1
  71. package/core/plugins/registry.ts +25 -21
  72. package/core/plugins/types.ts +147 -5
  73. package/core/server/backend-entry.ts +51 -0
  74. package/core/server/framework.ts +2 -2
  75. package/core/server/live/ComponentRegistry.ts +9 -26
  76. package/core/server/live/FileUploadManager.ts +1 -1
  77. package/core/server/live/auto-generated-components.ts +26 -0
  78. package/core/server/live/websocket-plugin.ts +211 -19
  79. package/core/server/middleware/errorHandling.ts +1 -1
  80. package/core/server/middleware/index.ts +4 -4
  81. package/core/server/plugins/database.ts +1 -2
  82. package/core/server/plugins/static-files-plugin.ts +259 -231
  83. package/core/server/plugins/swagger.ts +1 -1
  84. package/core/server/services/BaseService.ts +1 -1
  85. package/core/server/services/ServiceContainer.ts +1 -1
  86. package/core/server/services/index.ts +4 -4
  87. package/core/server/standalone.ts +16 -1
  88. package/core/testing/index.ts +1 -1
  89. package/core/testing/setup.ts +1 -1
  90. package/core/types/plugin.ts +6 -0
  91. package/core/utils/build-logger.ts +324 -0
  92. package/core/utils/config-schema.ts +2 -6
  93. package/core/utils/helpers.ts +14 -9
  94. package/core/utils/logger/startup-banner.ts +7 -33
  95. package/core/utils/regenerate-files.ts +69 -0
  96. package/core/utils/version.ts +6 -6
  97. package/create-fluxstack.ts +68 -25
  98. package/fluxstack.config.ts +138 -252
  99. package/package.json +3 -18
  100. package/plugins/crypto-auth/index.ts +52 -47
  101. package/plugins/crypto-auth/server/AuthMiddleware.ts +1 -1
  102. package/plugins/crypto-auth/server/middlewares/helpers.ts +16 -1
  103. package/vitest.config.ts +17 -26
  104. package/app/client/src/App.css +0 -883
  105. package/app/client/src/components/ErrorBoundary.tsx +0 -107
  106. package/app/client/src/components/ErrorDisplay.css +0 -365
  107. package/app/client/src/components/ErrorDisplay.tsx +0 -258
  108. package/app/client/src/components/FluxStackConfig.tsx +0 -1321
  109. package/app/client/src/components/HybridLiveCounter.tsx +0 -140
  110. package/app/client/src/components/LiveClock.tsx +0 -286
  111. package/app/client/src/components/MainLayout.tsx +0 -388
  112. package/app/client/src/components/SidebarNavigation.tsx +0 -391
  113. package/app/client/src/components/StateDemo.tsx +0 -178
  114. package/app/client/src/components/SystemMonitor.tsx +0 -1044
  115. package/app/client/src/components/UserProfile.tsx +0 -809
  116. package/app/client/src/hooks/useAuth.ts +0 -39
  117. package/app/client/src/hooks/useNotifications.ts +0 -56
  118. package/app/client/src/lib/errors.ts +0 -340
  119. package/app/client/src/lib/hooks/useErrorHandler.ts +0 -258
  120. package/app/client/src/lib/index.ts +0 -45
  121. package/app/client/src/pages/ApiDocs.tsx +0 -182
  122. package/app/client/src/pages/CryptoAuthPage.tsx +0 -394
  123. package/app/client/src/pages/Demo.tsx +0 -174
  124. package/app/client/src/pages/HybridLive.tsx +0 -263
  125. package/app/client/src/pages/Overview.tsx +0 -155
  126. package/app/client/src/store/README.md +0 -43
  127. package/app/client/src/store/index.ts +0 -16
  128. package/app/client/src/store/slices/uiSlice.ts +0 -151
  129. package/app/client/src/store/slices/userSlice.ts +0 -161
  130. package/app/client/src/test/README.md +0 -257
  131. package/app/client/src/test/setup.ts +0 -70
  132. package/app/client/src/test/types.ts +0 -12
  133. package/app/server/live/CounterComponent.ts +0 -191
  134. package/app/server/live/FluxStackConfig.ts +0 -534
  135. package/app/server/live/SidebarNavigation.ts +0 -157
  136. package/app/server/live/SystemMonitor.ts +0 -595
  137. package/app/server/live/SystemMonitorIntegration.ts +0 -151
  138. package/app/server/live/UserProfileComponent.ts +0 -141
  139. package/app/server/middleware/auth.ts +0 -136
  140. package/app/server/middleware/errorHandling.ts +0 -252
  141. package/app/server/middleware/index.ts +0 -10
  142. package/app/server/middleware/rateLimit.ts +0 -193
  143. package/app/server/middleware/requestLogging.ts +0 -215
  144. package/app/server/middleware/validation.ts +0 -270
  145. package/app/server/routes/config.ts +0 -145
  146. package/app/server/routes/crypto-auth-demo.routes.ts +0 -167
  147. package/app/server/routes/example-with-crypto-auth.routes.ts +0 -235
  148. package/app/server/routes/exemplo-posts.routes.ts +0 -161
  149. package/app/server/routes/upload.ts +0 -92
  150. package/app/server/services/NotificationService.ts +0 -302
  151. package/app/server/services/UserService.ts +0 -222
  152. package/app/server/services/index.ts +0 -46
  153. package/app/server/types/index.ts +0 -1
  154. package/config/build.config.ts +0 -24
@@ -1,140 +0,0 @@
1
- // 🔥 Simple Hybrid Live Counter - Server-Driven with Zustand
2
-
3
- import { useHybridLiveComponent } from '@/core/client'
4
-
5
- interface CounterState {
6
- count: number
7
- title: string
8
- step: number
9
- }
10
-
11
- interface HybridLiveCounterProps {
12
- initialCount?: number
13
- title?: string
14
- step?: number
15
- room?: string
16
- userId?: string
17
- }
18
-
19
- export function HybridLiveCounter({
20
- initialCount = 0,
21
- title = 'Simple Live Counter',
22
- step = 1,
23
- room,
24
- userId
25
- }: HybridLiveCounterProps = {}) {
26
- // Frontend provides initial state - server takes control after mount
27
- const initialState: CounterState = {
28
- count: initialCount,
29
- title,
30
- step
31
- }
32
-
33
- const {
34
- state,
35
- loading,
36
- error,
37
- connected,
38
- call,
39
- callAndWait
40
- } = useHybridLiveComponent<CounterState>('Counter', initialState, {
41
- debug: true,
42
- autoMount: true,
43
- room,
44
- userId
45
- })
46
-
47
- const handleIncrement = () => call('increment', state.step)
48
- const handleDecrement = () => call('decrement', state.step)
49
- const handleReset = () => call('reset')
50
-
51
- const handleGetStats = async () => {
52
- try {
53
- const response = await callAndWait('getStats')
54
- const stats = response.stats
55
- alert(`📊 Current: ${stats.current} | Min: ${stats.min} | Max: ${stats.max} | Avg: ${stats.average.toFixed(1)}`)
56
- } catch (err) {
57
- alert(`❌ Error: ${err instanceof Error ? err.message : 'Failed to get stats'}`)
58
- }
59
- }
60
-
61
- return (
62
- <div className="max-w-md mx-auto p-6 bg-white rounded-lg shadow-lg border">
63
- {/* Header */}
64
- <div className="text-center mb-6">
65
- <h1 className="text-2xl font-bold text-gray-800 mb-2">{state.title}</h1>
66
- <div className="flex justify-center gap-2 text-sm">
67
- <span className={`px-2 py-1 rounded text-xs ${
68
- connected ? 'bg-green-100 text-green-700' : 'bg-red-100 text-red-700'
69
- }`}>
70
- {connected ? '🟢 Connected' : '🔴 Disconnected'}
71
- </span>
72
- <span className="px-2 py-1 rounded text-xs bg-blue-100 text-blue-700">
73
- 🎯 Server-Driven
74
- </span>
75
- </div>
76
- </div>
77
-
78
- {/* Error Display */}
79
- {error && (
80
- <div className="mb-4 p-3 bg-red-100 border border-red-300 text-red-700 rounded text-sm">
81
- ❌ {error}
82
- </div>
83
- )}
84
-
85
- {/* Counter Display */}
86
- <div className="text-center mb-6">
87
- <div className="text-5xl font-bold text-blue-600 mb-2">
88
- {state.count}
89
- </div>
90
- <div className="text-sm text-gray-500">
91
- Step: {state.step}
92
- </div>
93
- </div>
94
-
95
- {/* Control Buttons */}
96
- <div className="grid grid-cols-2 gap-3 mb-4">
97
- <button
98
- onClick={handleDecrement}
99
- disabled={loading || !connected}
100
- className="px-4 py-2 bg-red-500 hover:bg-red-600 disabled:bg-gray-300 text-white font-bold rounded transition-colors"
101
- >
102
- - {state.step}
103
- </button>
104
- <button
105
- onClick={handleIncrement}
106
- disabled={loading || !connected}
107
- className="px-4 py-2 bg-green-500 hover:bg-green-600 disabled:bg-gray-300 text-white font-bold rounded transition-colors"
108
- >
109
- + {state.step}
110
- </button>
111
- </div>
112
-
113
- {/* Action Buttons */}
114
- <div className="grid grid-cols-2 gap-3">
115
- <button
116
- onClick={handleReset}
117
- disabled={loading || !connected}
118
- className="px-3 py-2 bg-gray-500 hover:bg-gray-600 disabled:bg-gray-300 text-white text-sm rounded transition-colors"
119
- >
120
- 🔄 Reset
121
- </button>
122
- <button
123
- onClick={handleGetStats}
124
- disabled={loading || !connected}
125
- className="px-3 py-2 bg-blue-500 hover:bg-blue-600 disabled:bg-gray-300 text-white text-sm rounded transition-colors"
126
- >
127
- 📊 Stats
128
- </button>
129
- </div>
130
-
131
- {/* Loading Indicator */}
132
- {loading && (
133
- <div className="mt-4 text-center">
134
- <div className="inline-block animate-spin rounded-full h-4 w-4 border-2 border-blue-600 border-t-transparent"></div>
135
- <span className="ml-2 text-sm text-gray-600">Loading...</span>
136
- </div>
137
- )}
138
- </div>
139
- )
140
- }
@@ -1,286 +0,0 @@
1
- // 🔥 LiveClock - Real-time Clock Client Component
2
- import React, { useState } from 'react';
3
- import { useHybridLiveComponent } from '@/core/client';
4
- import {
5
- FaClock,
6
- FaCog,
7
- FaSync,
8
- FaServer,
9
- FaCalendarAlt,
10
- FaStopwatch,
11
- FaGlobe,
12
- FaEye,
13
- FaEyeSlash
14
- } from 'react-icons/fa';
15
-
16
- interface LiveClockState {
17
- currentTime: string;
18
- timeZone: string;
19
- format: '12h' | '24h';
20
- showSeconds: boolean;
21
- showDate: boolean;
22
- lastSync: Date;
23
- serverUptime: number;
24
- }
25
-
26
- const initialState: LiveClockState = {
27
- currentTime: "Loading...",
28
- timeZone: "America/Sao_Paulo",
29
- format: "24h",
30
- showSeconds: true,
31
- showDate: true,
32
- lastSync: new Date(),
33
- serverUptime: 0,
34
- };
35
-
36
- export function LiveClock() {
37
- const { state, call, connected, loading, status } = useHybridLiveComponent<LiveClockState>('LiveClock', initialState, {
38
- debug: true
39
- });
40
-
41
- const [showSettings, setShowSettings] = useState(false);
42
-
43
- if (!connected || status !== 'synced') {
44
- const getStatusMessage = () => {
45
- switch (status) {
46
- case 'connecting':
47
- return '🔄 Conectando ao relógio do servidor...';
48
- case 'reconnecting':
49
- return '🔄 Reconectando relógio...';
50
- case 'mounting':
51
- return '🚀 Sincronizando horário...';
52
- case 'loading':
53
- return '⏳ Carregando relógio...';
54
- case 'error':
55
- return '❌ Erro na sincronização';
56
- default:
57
- return '🔄 Preparando relógio...';
58
- }
59
- };
60
-
61
- return (
62
- <div className="flex items-center justify-center p-8 border-2 border-dashed border-gray-300 rounded-lg bg-gradient-to-br from-blue-50 to-indigo-100">
63
- <div className="text-center">
64
- <FaClock size={48} className="mx-auto mb-4 text-blue-500 animate-pulse" />
65
- <p className="text-gray-700 font-medium">{getStatusMessage()}</p>
66
- </div>
67
- </div>
68
- );
69
- }
70
-
71
- const getCurrentDate = () => {
72
- return new Date().toLocaleDateString('pt-BR', {
73
- weekday: 'long',
74
- year: 'numeric',
75
- month: 'long',
76
- day: 'numeric'
77
- });
78
- };
79
-
80
- const formatUptime = (seconds: number) => {
81
- const hours = Math.floor(seconds / 3600);
82
- const minutes = Math.floor((seconds % 3600) / 60);
83
- const secs = seconds % 60;
84
-
85
- if (hours > 0) {
86
- return `${hours}h ${minutes}m ${secs}s`;
87
- } else if (minutes > 0) {
88
- return `${minutes}m ${secs}s`;
89
- } else {
90
- return `${secs}s`;
91
- }
92
- };
93
-
94
- const handleFormatToggle = async () => {
95
- const newFormat = state.format === '24h' ? '12h' : '24h';
96
- try {
97
- await call('setTimeFormat', { format: newFormat });
98
- } catch (error) {
99
- console.error('Error changing format:', error);
100
- }
101
- };
102
-
103
- const handleToggleSeconds = async () => {
104
- try {
105
- await call('toggleSeconds');
106
- } catch (error) {
107
- console.error('Error toggling seconds:', error);
108
- }
109
- };
110
-
111
- const handleToggleDate = async () => {
112
- try {
113
- await call('toggleDate');
114
- } catch (error) {
115
- console.error('Error toggling date:', error);
116
- }
117
- };
118
-
119
- const handleSyncTime = async () => {
120
- try {
121
- await call('syncTime');
122
- } catch (error) {
123
- console.error('Error syncing time:', error);
124
- }
125
- };
126
-
127
- const handleGetServerInfo = async () => {
128
- try {
129
- const result = await call('getServerInfo');
130
- console.log('Server info:', result);
131
-
132
- if (result && result.info) {
133
- alert(`Server Info:\nTime: ${result.info.localTime}\nUptime: ${result.info.uptimeFormatted}\nTimezone: ${result.info.timezone}`);
134
- } else {
135
- console.error('Invalid server info response:', result);
136
- alert('Erro: Resposta inválida do servidor');
137
- }
138
- } catch (error) {
139
- console.error('Error getting server info:', error);
140
- alert(`Erro ao obter info do servidor: ${error instanceof Error ? error.message : 'Erro desconhecido'}`);
141
- }
142
- };
143
-
144
- return (
145
- <div className="bg-gradient-to-br from-slate-50 to-blue-50 border border-gray-200 rounded-xl shadow-lg p-6 m-4 relative overflow-hidden">
146
- {/* Background decoration */}
147
- <div className="absolute top-0 right-0 w-32 h-32 bg-gradient-to-br from-blue-200 to-indigo-300 rounded-full opacity-20 -translate-y-16 translate-x-16"></div>
148
-
149
- {/* Header */}
150
- <div className="flex items-center justify-between mb-6 relative z-10">
151
- <div className="flex items-center gap-3">
152
- <FaClock size={28} className="text-blue-600" />
153
- <h2 className="text-2xl font-bold text-gray-800">Live Clock</h2>
154
- </div>
155
-
156
- <div className="flex items-center gap-2">
157
- <span className={`px-3 py-1 rounded-full text-xs font-medium flex items-center gap-1 ${
158
- connected ? 'bg-green-100 text-green-800' : 'bg-red-100 text-red-800'
159
- }`}>
160
- {connected ? '🟢 Sincronizado' : '🔴 Desconectado'}
161
- </span>
162
-
163
- <button
164
- onClick={() => setShowSettings(!showSettings)}
165
- className="p-2 rounded-lg bg-gray-100 hover:bg-gray-200 transition-colors"
166
- >
167
- <FaCog className="text-gray-600" />
168
- </button>
169
- </div>
170
- </div>
171
-
172
- {/* Main Clock Display */}
173
- <div className="text-center mb-6 relative z-10">
174
- <div className="bg-white rounded-2xl p-8 shadow-inner border-2 border-gray-100">
175
- <div className="text-6xl font-mono font-bold text-gray-800 mb-2 tracking-wider">
176
- {state.currentTime}
177
- </div>
178
-
179
- {state.showDate && (
180
- <div className="text-lg text-gray-600 mb-2 flex items-center justify-center gap-2">
181
- <FaCalendarAlt className="text-blue-500" />
182
- {getCurrentDate()}
183
- </div>
184
- )}
185
-
186
- <div className="flex items-center justify-center gap-4 text-sm text-gray-500">
187
- <div className="flex items-center gap-1">
188
- <FaGlobe />
189
- <span>{state.timeZone}</span>
190
- </div>
191
- <div className="flex items-center gap-1">
192
- <FaStopwatch />
193
- <span>Uptime: {formatUptime(state.serverUptime)}</span>
194
- </div>
195
- </div>
196
- </div>
197
- </div>
198
-
199
- {/* Settings Panel */}
200
- {showSettings && (
201
- <div className="bg-white rounded-xl p-4 mb-4 border shadow-sm relative z-10">
202
- <h3 className="text-lg font-semibold text-gray-800 mb-3 flex items-center gap-2">
203
- <FaCog />
204
- Configurações
205
- </h3>
206
-
207
- <div className="grid grid-cols-2 md:grid-cols-4 gap-3">
208
- <button
209
- onClick={handleFormatToggle}
210
- disabled={loading}
211
- className="px-3 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600 disabled:opacity-50 disabled:cursor-not-allowed text-sm flex items-center justify-center gap-1"
212
- >
213
- <FaClock />
214
- {state.format === '24h' ? '12h' : '24h'}
215
- </button>
216
-
217
- <button
218
- onClick={handleToggleSeconds}
219
- disabled={loading}
220
- className="px-3 py-2 bg-green-500 text-white rounded-lg hover:bg-green-600 disabled:opacity-50 disabled:cursor-not-allowed text-sm flex items-center justify-center gap-1"
221
- >
222
- {state.showSeconds ? <FaEyeSlash /> : <FaEye />}
223
- Segundos
224
- </button>
225
-
226
- <button
227
- onClick={handleToggleDate}
228
- disabled={loading}
229
- className="px-3 py-2 bg-purple-500 text-white rounded-lg hover:bg-purple-600 disabled:opacity-50 disabled:cursor-not-allowed text-sm flex items-center justify-center gap-1"
230
- >
231
- <FaCalendarAlt />
232
- Data
233
- </button>
234
-
235
- <button
236
- onClick={handleSyncTime}
237
- disabled={loading}
238
- className="px-3 py-2 bg-orange-500 text-white rounded-lg hover:bg-orange-600 disabled:opacity-50 disabled:cursor-not-allowed text-sm flex items-center justify-center gap-1"
239
- >
240
- <FaSync />
241
- Sync
242
- </button>
243
- </div>
244
- </div>
245
- )}
246
-
247
- {/* Action Buttons */}
248
- <div className="flex gap-3 flex-wrap relative z-10">
249
- <button
250
- onClick={handleGetServerInfo}
251
- disabled={loading}
252
- className="px-4 py-2 bg-indigo-500 text-white rounded-lg hover:bg-indigo-600 disabled:opacity-50 disabled:cursor-not-allowed text-sm flex items-center gap-2"
253
- >
254
- <FaServer />
255
- Info do Servidor
256
- </button>
257
-
258
- <button
259
- onClick={handleSyncTime}
260
- disabled={loading}
261
- className="px-4 py-2 bg-emerald-500 text-white rounded-lg hover:bg-emerald-600 disabled:opacity-50 disabled:cursor-not-allowed text-sm flex items-center gap-2"
262
- >
263
- <FaSync />
264
- Sincronizar Agora
265
- </button>
266
- </div>
267
-
268
- {/* Status Footer */}
269
- <div className="mt-4 text-xs text-gray-500 text-center relative z-10">
270
- Última sincronização: {new Date(state.lastSync).toLocaleTimeString()} •
271
- Formato: {state.format} •
272
- Servidor rodando há {formatUptime(state.serverUptime)}
273
- </div>
274
-
275
- {/* Loading Overlay */}
276
- {loading && (
277
- <div className="absolute inset-0 bg-white bg-opacity-75 flex items-center justify-center rounded-xl z-20">
278
- <div className="flex items-center gap-2">
279
- <div className="animate-spin rounded-full h-6 w-6 border-b-2 border-blue-500"></div>
280
- <span className="text-gray-700 font-medium">Sincronizando...</span>
281
- </div>
282
- </div>
283
- )}
284
- </div>
285
- );
286
- }