blackcoffee2 2.1.0

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 (170) hide show
  1. package/CHANGELOG.md +664 -0
  2. package/LICENSE +201 -0
  3. package/NOTICE +25 -0
  4. package/README.md +246 -0
  5. package/apps.zip +0 -0
  6. package/bin/adminclient +105 -0
  7. package/bin/blackcoffee +133 -0
  8. package/cli/admin-users.js +282 -0
  9. package/cli/commands/app.js +561 -0
  10. package/cli/commands/config.js +182 -0
  11. package/cli/commands/db.js +257 -0
  12. package/cli/commands/server.js +200 -0
  13. package/config/applications.json +5 -0
  14. package/config/database.json +28 -0
  15. package/config/database.json.example +23 -0
  16. package/config/server.json +32 -0
  17. package/controllers/admin/AdminController.js +529 -0
  18. package/controllers/admin/AdminViewController.js +90 -0
  19. package/controllers/admin/AuthController.js +293 -0
  20. package/controllers/admin/DatabaseAdminController.js +218 -0
  21. package/core/SQLiteAdapter.js +333 -0
  22. package/core/appLoader.js +385 -0
  23. package/core/databasePoolManager.js +431 -0
  24. package/core/hotReload.js +363 -0
  25. package/data/ADMIN-README.md +145 -0
  26. package/data/CHANGELOG.md +48 -0
  27. package/data/GTK3-NODE-PROPOSALS.md +410 -0
  28. package/data/admin-db.js +150 -0
  29. package/data/admin-gui.js +452 -0
  30. package/data/blackcoffee_admin.db-shm +0 -0
  31. package/data/blackcoffee_admin.db-wal +0 -0
  32. package/data/migrations/001_create_admin_users.sql +33 -0
  33. package/docs/APP_HOOKS_HANDLER.md +432 -0
  34. package/docs/APP_HOOKS_REQUIREMENTS.md +588 -0
  35. package/docs/ARCHITECTURE.md +435 -0
  36. package/docs/CREAR_APP_Y_USAR_POOLS.md +1595 -0
  37. package/docs/EVENTS_APP_MANUAL.md +289 -0
  38. package/docs/INSITU_BINARY_UPLOAD_PROPOSAL.md +186 -0
  39. package/docs/INSITU_FIREWALL_EXCEPTION.md +187 -0
  40. package/docs/ROADMAP.md +242 -0
  41. package/docs/ROADMAP.md.backup +243 -0
  42. package/includes/404-hooks.js +423 -0
  43. package/includes/adminAuth.js +214 -0
  44. package/includes/adminExtension.js +53 -0
  45. package/includes/appHooks.js +302 -0
  46. package/includes/initAdminDb.js +115 -0
  47. package/includes/routeLoader.js +67 -0
  48. package/includes/sessions.js +223 -0
  49. package/issues/001-duplicate-module-loading.md +92 -0
  50. package/manuales/ADMIN_EXTENSION_COMMANDS_MANUAL.md +261 -0
  51. package/manuales/ADMIN_EXTENSION_HOOK_EXAMPLE.md +28 -0
  52. package/manuales/ADMIN_EXTENSION_INTEGRATION_MANUAL.md +232 -0
  53. package/manuales/CACHE_REGEX_COMMANDS.md +136 -0
  54. package/manuales/CACHE_SYSTEM_MAP.md +206 -0
  55. package/manuales/CREACION_DE_CONTROLADORES_INSITU.md +383 -0
  56. package/manuales/QUEUE_CLI_MODULE_MANUAL.md +289 -0
  57. package/manuales/QUEUE_SYSTEM_MANUAL.md +320 -0
  58. package/manuales/ROUTE_CACHE_MODULE_MANUAL.md +205 -0
  59. package/manuales/SESSION_MANAGER_GUIDE.md +529 -0
  60. package/manuales/SESSION_SECURITY_FLAGS.md +174 -0
  61. package/manuales/WAF_MODULE_MANUAL.md +229 -0
  62. package/manuales/after_route_handler_filter_example.md +116 -0
  63. package/manuales/after_route_handler_usage.md +130 -0
  64. package/manuales/an/303/241lisis-completo-insitu-framework.md +213 -0
  65. package/manuales/async_hooks_promises_guide.md +325 -0
  66. package/manuales/before_route_handler_filter_example.md +97 -0
  67. package/manuales/before_route_handler_usage.md +122 -0
  68. package/manuales/hooks_chaining_conditions_guide.md +261 -0
  69. package/manuales/hooks_filters_documentation.md +493 -0
  70. package/manuales/hooks_filters_documentation_en.md +493 -0
  71. package/manuales/hooks_vs_middlewares_comparison.md +87 -0
  72. package/manuales/manual-mvc-completo.md +934 -0
  73. package/manuales/modulos_administracion.md +89 -0
  74. package/manuales/router_execution_points.md +74 -0
  75. package/manuales/static_file_hooks_usage.md +222 -0
  76. package/models/AdminUserModel.js +132 -0
  77. package/package.json +45 -0
  78. package/programatically/PRoutes.js +89 -0
  79. package/programatically/initFlow.js +211 -0
  80. package/public/admin/css/db-pools.css +336 -0
  81. package/public/admin/css/styles.css +310 -0
  82. package/public/admin/database.html +312 -0
  83. package/public/admin/index.html +116 -0
  84. package/public/admin/js/app.js +470 -0
  85. package/public/admin/js/db-pools.js +253 -0
  86. package/public/admin/login.html +278 -0
  87. package/public/assets/css/styles.css +477 -0
  88. package/public/assets/js/main.js +89 -0
  89. package/public/index.html +136 -0
  90. package/public/templates/404.html +158 -0
  91. package/routes/admin-views.json +20 -0
  92. package/routes/admin.json +38 -0
  93. package/routes/auth.json +32 -0
  94. package/routes/static.json +18 -0
  95. package/server.js +299 -0
  96. package/test-aplicacion.con-logisession/BlackCoffee.js +226 -0
  97. package/test-aplicacion.con-logisession/SSL_SETUP.md +53 -0
  98. package/test-aplicacion.con-logisession/certs/ca-certificate.pem +32 -0
  99. package/test-aplicacion.con-logisession/certs/ca-private-key.pem +52 -0
  100. package/test-aplicacion.con-logisession/certs/certificate-2048.pem +22 -0
  101. package/test-aplicacion.con-logisession/certs/certificate.pem +32 -0
  102. package/test-aplicacion.con-logisession/certs/private-key-2048.pem +28 -0
  103. package/test-aplicacion.con-logisession/certs/private-key.pem +52 -0
  104. package/test-aplicacion.con-logisession/config/iaQueueSetup.js +84 -0
  105. package/test-aplicacion.con-logisession/config/qwen-rules.json +39 -0
  106. package/test-aplicacion.con-logisession/controllers/analyticsController.js +117 -0
  107. package/test-aplicacion.con-logisession/controllers/auth/AdminAuthController.js +142 -0
  108. package/test-aplicacion.con-logisession/controllers/auth/AuthController.js +439 -0
  109. package/test-aplicacion.con-logisession/controllers/auth/AuthViewController.js +223 -0
  110. package/test-aplicacion.con-logisession/controllers/endpointController.js +66 -0
  111. package/test-aplicacion.con-logisession/controllers/example.js +183 -0
  112. package/test-aplicacion.con-logisession/controllers/iaQueueController.js +367 -0
  113. package/test-aplicacion.con-logisession/controllers/queueController.js +206 -0
  114. package/test-aplicacion.con-logisession/controllers/qwenQueueController.js +197 -0
  115. package/test-aplicacion.con-logisession/controllers/test.js +0 -0
  116. package/test-aplicacion.con-logisession/controllers/tracking/EventsNoFinishController.js +78 -0
  117. package/test-aplicacion.con-logisession/controllers/tracking/TrackingController.js +412 -0
  118. package/test-aplicacion.con-logisession/controllers/tracking/TrackingControllerWithLoadModel.js +437 -0
  119. package/test-aplicacion.con-logisession/hooks/admin-hooks.js +20 -0
  120. package/test-aplicacion.con-logisession/hooks/general-hooks.js +97 -0
  121. package/test-aplicacion.con-logisession/hooks/queue-hooks.js +64 -0
  122. package/test-aplicacion.con-logisession/hooks/route-directory-hooks.js +38 -0
  123. package/test-aplicacion.con-logisession/hooks/security-hooks.js +24 -0
  124. package/test-aplicacion.con-logisession/insitu-admin-client/README.md +69 -0
  125. package/test-aplicacion.con-logisession/insitu-admin-client/package.json +23 -0
  126. package/test-aplicacion.con-logisession/insitu-admin-client.js +257 -0
  127. package/test-aplicacion.con-logisession/models/ExampleModel.js +88 -0
  128. package/test-aplicacion.con-logisession/models/QueueJobModel.js +263 -0
  129. package/test-aplicacion.con-logisession/models/TokenModel.js +207 -0
  130. package/test-aplicacion.con-logisession/models/auth/AuthModel.js +66 -0
  131. package/test-aplicacion.con-logisession/models/auth/UserModel.js +189 -0
  132. package/test-aplicacion.con-logisession/models/tracking/CompletedCartModel.js +213 -0
  133. package/test-aplicacion.con-logisession/models/tracking/EventModel.js +366 -0
  134. package/test-aplicacion.con-logisession/models/tracking/EventsNoFinishModel.js +131 -0
  135. package/test-aplicacion.con-logisession/models/tracking/SessionModel.js +360 -0
  136. package/test-aplicacion.con-logisession/models/tracking/SiteFlowModel.js +286 -0
  137. package/test-aplicacion.con-logisession/models/tracking/TokenModel.js +207 -0
  138. package/test-aplicacion.con-logisession/package-lock.json +3313 -0
  139. package/test-aplicacion.con-logisession/package.json +32 -0
  140. package/test-aplicacion.con-logisession/public/blackcoffee-welcome/index.html +1339 -0
  141. package/test-aplicacion.con-logisession/public/css/style.css +64 -0
  142. package/test-aplicacion.con-logisession/public/ejemplo-estatica/index.html +18 -0
  143. package/test-aplicacion.con-logisession/public/ejemplo-estatica/script.js +16 -0
  144. package/test-aplicacion.con-logisession/public/ejemplo-estatica/styles.css +43 -0
  145. package/test-aplicacion.con-logisession/public/images/logo.svg +7 -0
  146. package/test-aplicacion.con-logisession/public/js/main.js +67 -0
  147. package/test-aplicacion.con-logisession/routes/analytics-routes.json +8 -0
  148. package/test-aplicacion.con-logisession/routes/auth-routes.json +98 -0
  149. package/test-aplicacion.con-logisession/routes/blackcoffee-welcome-routes.json +20 -0
  150. package/test-aplicacion.con-logisession/routes/duplicate-test-routes.json.disabled +16 -0
  151. package/test-aplicacion.con-logisession/routes/ejemplo-estatica-routes.json +11 -0
  152. package/test-aplicacion.con-logisession/routes/endpoints-routes.json +8 -0
  153. package/test-aplicacion.con-logisession/routes/ia-queue-routes.json +26 -0
  154. package/test-aplicacion.con-logisession/routes/product-routes.json.disabled +20 -0
  155. package/test-aplicacion.con-logisession/routes/queue-routes.json +32 -0
  156. package/test-aplicacion.con-logisession/routes/qwen-routes.json +14 -0
  157. package/test-aplicacion.con-logisession/routes/static-routes.json +29 -0
  158. package/test-aplicacion.con-logisession/routes/tracking-routes.json +58 -0
  159. package/test-aplicacion.con-logisession/routes/tracking-with-loadmodel-routes.json +51 -0
  160. package/test-aplicacion.con-logisession/utils/dbAdapter.js +88 -0
  161. package/test-aplicacion.con-logisession/utils/qbWrapper.js +4 -0
  162. package/test-aplicacion.con-logisession/utils/queueProcessor.js +305 -0
  163. package/test-aplicacion.con-logisession/utils/qwenRulesService.js +131 -0
  164. package/test-aplicacion.con-logisession/utils/tokenHelper.js +22 -0
  165. package/test-aplicacion.con-logisession/views/auth/dashboard.html +443 -0
  166. package/test-aplicacion.con-logisession/views/auth/forgot-password.html +200 -0
  167. package/test-aplicacion.con-logisession/views/auth/login.html +213 -0
  168. package/test-aplicacion.con-logisession/views/auth/register.html +294 -0
  169. package/test-aplicacion.con-logisession/views/contact/form.html +47 -0
  170. package/test-aplicacion.con-logisession/views/products/index.html +39 -0
@@ -0,0 +1,213 @@
1
+ <!DOCTYPE html>
2
+ <html lang="es">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Iniciar Sesión - BlackCoffee</title>
7
+ <style>
8
+ * {
9
+ margin: 0;
10
+ padding: 0;
11
+ box-sizing: border-box;
12
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
13
+ }
14
+
15
+ body {
16
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
17
+ min-height: 100vh;
18
+ display: flex;
19
+ align-items: center;
20
+ justify-content: center;
21
+ padding: 20px;
22
+ }
23
+
24
+ .login-container {
25
+ background: white;
26
+ padding: 40px;
27
+ border-radius: 10px;
28
+ box-shadow: 0 15px 35px rgba(0, 0, 0, 0.1);
29
+ width: 100%;
30
+ max-width: 400px;
31
+ }
32
+
33
+ .login-header {
34
+ text-align: center;
35
+ margin-bottom: 30px;
36
+ }
37
+
38
+ .login-header h1 {
39
+ color: #333;
40
+ font-size: 28px;
41
+ margin-bottom: 10px;
42
+ }
43
+
44
+ .login-header p {
45
+ color: #666;
46
+ font-size: 14px;
47
+ }
48
+
49
+ .form-group {
50
+ margin-bottom: 20px;
51
+ }
52
+
53
+ .form-group label {
54
+ display: block;
55
+ margin-bottom: 8px;
56
+ color: #333;
57
+ font-weight: 500;
58
+ }
59
+
60
+ .form-group input {
61
+ width: 100%;
62
+ padding: 12px 15px;
63
+ border: 2px solid #e1e1e1;
64
+ border-radius: 5px;
65
+ font-size: 16px;
66
+ transition: border-color 0.3s ease;
67
+ }
68
+
69
+ .form-group input:focus {
70
+ outline: none;
71
+ border-color: #667eea;
72
+ }
73
+
74
+ .btn {
75
+ width: 100%;
76
+ padding: 12px;
77
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
78
+ color: white;
79
+ border: none;
80
+ border-radius: 5px;
81
+ font-size: 16px;
82
+ font-weight: 600;
83
+ cursor: pointer;
84
+ transition: transform 0.2s ease, box-shadow 0.2s ease;
85
+ }
86
+
87
+ .btn:hover {
88
+ transform: translateY(-2px);
89
+ box-shadow: 0 5px 15px rgba(102, 126, 234, 0.4);
90
+ }
91
+
92
+ .btn:active {
93
+ transform: translateY(0);
94
+ }
95
+
96
+ .login-footer {
97
+ text-align: center;
98
+ margin-top: 20px;
99
+ color: #666;
100
+ font-size: 14px;
101
+ }
102
+
103
+ .login-footer a {
104
+ color: #667eea;
105
+ text-decoration: none;
106
+ font-weight: 500;
107
+ }
108
+
109
+ .login-footer a:hover {
110
+ text-decoration: underline;
111
+ }
112
+
113
+ .error-message {
114
+ display: none;
115
+ background: #fee;
116
+ color: #c33;
117
+ padding: 10px;
118
+ border-radius: 5px;
119
+ margin-bottom: 15px;
120
+ text-align: center;
121
+ font-size: 14px;
122
+ }
123
+
124
+ .success-message {
125
+ display: none;
126
+ background: #efe;
127
+ color: #363;
128
+ padding: 10px;
129
+ border-radius: 5px;
130
+ margin-bottom: 15px;
131
+ text-align: center;
132
+ font-size: 14px;
133
+ }
134
+ </style>
135
+ </head>
136
+ <body>
137
+ <div class="login-container">
138
+ <div class="login-header">
139
+ <h1>Iniciar Sesión</h1>
140
+ <p>Accede a tu cuenta para continuar</p>
141
+ </div>
142
+
143
+ <div id="errorMessage" class="error-message"></div>
144
+ <div id="successMessage" class="success-message"></div>
145
+
146
+ <form id="loginForm">
147
+ <div class="form-group">
148
+ <label for="username">Usuario o Email</label>
149
+ <input type="text" id="username" name="username" required placeholder="Ingresa tu usuario o email">
150
+ </div>
151
+
152
+ <div class="form-group">
153
+ <label for="password">Contraseña</label>
154
+ <input type="password" id="password" name="password" required placeholder="Ingresa tu contraseña">
155
+ </div>
156
+
157
+ <button type="submit" class="btn">Iniciar Sesión</button>
158
+ </form>
159
+
160
+ <div class="login-footer">
161
+ <p>¿No tienes una cuenta? <a href="/register">Regístrate aquí</a></p>
162
+ <p><a href="/forgot-password">¿Olvidaste tu contraseña?</a></p>
163
+ </div>
164
+ </div>
165
+
166
+ <script>
167
+ document.getElementById('loginForm').addEventListener('submit', async (e) => {
168
+ e.preventDefault();
169
+
170
+ const username = document.getElementById('username').value;
171
+ const password = document.getElementById('password').value;
172
+ const errorMessage = document.getElementById('errorMessage');
173
+ const successMessage = document.getElementById('successMessage');
174
+
175
+ // Ocultar mensajes anteriores
176
+ errorMessage.style.display = 'none';
177
+ successMessage.style.display = 'none';
178
+
179
+ try {
180
+ const response = await fetch('/api/auth/login', {
181
+ method: 'POST',
182
+ headers: {
183
+ 'Content-Type': 'application/json',
184
+ },
185
+ body: JSON.stringify({ username, password })
186
+ });
187
+
188
+ const data = await response.json();
189
+
190
+ if (data.success) {
191
+ // Guardar el token en localStorage
192
+ localStorage.setItem('authToken', data.token);
193
+
194
+ // Mostrar mensaje de éxito
195
+ successMessage.textContent = 'Inicio de sesión exitoso. Redirigiendo...';
196
+ successMessage.style.display = 'block';
197
+
198
+ // Redirigir al dashboard o página principal
199
+ window.location.href = '/dashboard';
200
+ } else {
201
+ // Mostrar mensaje de error
202
+ errorMessage.textContent = data.error || 'Credenciales inválidas';
203
+ errorMessage.style.display = 'block';
204
+ }
205
+ } catch (error) {
206
+ console.error('Error en el inicio de sesión:', error);
207
+ errorMessage.textContent = 'Error de conexión. Por favor, inténtalo de nuevo.';
208
+ errorMessage.style.display = 'block';
209
+ }
210
+ });
211
+ </script>
212
+ </body>
213
+ </html>
@@ -0,0 +1,294 @@
1
+ <!DOCTYPE html>
2
+ <html lang="es">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Registrarse - BlackCoffee</title>
7
+ <style>
8
+ * {
9
+ margin: 0;
10
+ padding: 0;
11
+ box-sizing: border-box;
12
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
13
+ }
14
+
15
+ body {
16
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
17
+ min-height: 100vh;
18
+ display: flex;
19
+ align-items: center;
20
+ justify-content: center;
21
+ padding: 20px;
22
+ }
23
+
24
+ .register-container {
25
+ background: white;
26
+ padding: 40px;
27
+ border-radius: 10px;
28
+ box-shadow: 0 15px 35px rgba(0, 0, 0, 0.1);
29
+ width: 100%;
30
+ max-width: 450px;
31
+ }
32
+
33
+ .register-header {
34
+ text-align: center;
35
+ margin-bottom: 30px;
36
+ }
37
+
38
+ .register-header h1 {
39
+ color: #333;
40
+ font-size: 28px;
41
+ margin-bottom: 10px;
42
+ }
43
+
44
+ .register-header p {
45
+ color: #666;
46
+ font-size: 14px;
47
+ }
48
+
49
+ .form-group {
50
+ margin-bottom: 20px;
51
+ }
52
+
53
+ .form-group label {
54
+ display: block;
55
+ margin-bottom: 8px;
56
+ color: #333;
57
+ font-weight: 500;
58
+ }
59
+
60
+ .form-group input {
61
+ width: 100%;
62
+ padding: 12px 15px;
63
+ border: 2px solid #e1e1e1;
64
+ border-radius: 5px;
65
+ font-size: 16px;
66
+ transition: border-color 0.3s ease;
67
+ }
68
+
69
+ .form-group input:focus {
70
+ outline: none;
71
+ border-color: #667eea;
72
+ }
73
+
74
+ .btn {
75
+ width: 100%;
76
+ padding: 12px;
77
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
78
+ color: white;
79
+ border: none;
80
+ border-radius: 5px;
81
+ font-size: 16px;
82
+ font-weight: 600;
83
+ cursor: pointer;
84
+ transition: transform 0.2s ease, box-shadow 0.2s ease;
85
+ }
86
+
87
+ .btn:hover {
88
+ transform: translateY(-2px);
89
+ box-shadow: 0 5px 15px rgba(102, 126, 234, 0.4);
90
+ }
91
+
92
+ .btn:active {
93
+ transform: translateY(0);
94
+ }
95
+
96
+ .register-footer {
97
+ text-align: center;
98
+ margin-top: 20px;
99
+ color: #666;
100
+ font-size: 14px;
101
+ }
102
+
103
+ .register-footer a {
104
+ color: #667eea;
105
+ text-decoration: none;
106
+ font-weight: 500;
107
+ }
108
+
109
+ .register-footer a:hover {
110
+ text-decoration: underline;
111
+ }
112
+
113
+ .error-message {
114
+ display: none;
115
+ background: #fee;
116
+ color: #c33;
117
+ padding: 10px;
118
+ border-radius: 5px;
119
+ margin-bottom: 15px;
120
+ text-align: center;
121
+ font-size: 14px;
122
+ }
123
+
124
+ .success-message {
125
+ display: none;
126
+ background: #efe;
127
+ color: #363;
128
+ padding: 10px;
129
+ border-radius: 5px;
130
+ margin-bottom: 15px;
131
+ text-align: center;
132
+ font-size: 14px;
133
+ }
134
+
135
+ .password-strength {
136
+ height: 5px;
137
+ background: #eee;
138
+ border-radius: 3px;
139
+ margin-top: 5px;
140
+ overflow: hidden;
141
+ }
142
+
143
+ .strength-meter {
144
+ height: 100%;
145
+ width: 0%;
146
+ background: #ccc;
147
+ transition: width 0.3s, background 0.3s;
148
+ }
149
+ </style>
150
+ </head>
151
+ <body>
152
+ <div class="register-container">
153
+ <div class="register-header">
154
+ <h1>Crear Cuenta</h1>
155
+ <p>Regístrate para acceder a todas las funcionalidades</p>
156
+ </div>
157
+
158
+ <div id="errorMessage" class="error-message"></div>
159
+ <div id="successMessage" class="success-message"></div>
160
+
161
+ <form id="registerForm">
162
+ <div class="form-group">
163
+ <label for="username">Nombre de Usuario</label>
164
+ <input type="text" id="username" name="username" required placeholder="Ingresa tu nombre de usuario">
165
+ </div>
166
+
167
+ <div class="form-group">
168
+ <label for="email">Email</label>
169
+ <input type="email" id="email" name="email" required placeholder="Ingresa tu email">
170
+ </div>
171
+
172
+ <div class="form-group">
173
+ <label for="password">Contraseña</label>
174
+ <input type="password" id="password" name="password" required placeholder="Crea una contraseña segura">
175
+ <div class="password-strength">
176
+ <div id="strengthMeter" class="strength-meter"></div>
177
+ </div>
178
+ </div>
179
+
180
+ <div class="form-group">
181
+ <label for="confirmPassword">Confirmar Contraseña</label>
182
+ <input type="password" id="confirmPassword" name="confirmPassword" required placeholder="Confirma tu contraseña">
183
+ </div>
184
+
185
+ <button type="submit" class="btn">Registrarse</button>
186
+ </form>
187
+
188
+ <div class="register-footer">
189
+ <p>¿Ya tienes una cuenta? <a href="/login">Inicia sesión aquí</a></p>
190
+ </div>
191
+ </div>
192
+
193
+ <script>
194
+ // Función para evaluar la fortaleza de la contraseña
195
+ function checkPasswordStrength(password) {
196
+ let strength = 0;
197
+ const length = password.length;
198
+ const hasLower = /[a-z]/.test(password);
199
+ const hasUpper = /[A-Z]/.test(password);
200
+ const hasNumber = /\d/.test(password);
201
+ const hasSpecial = /[!@#$%^&*(),.?":{}|<>]/.test(password);
202
+
203
+ if (length > 0) strength += 1;
204
+ if (length >= 6) strength += 1;
205
+ if (length >= 8) strength += 1;
206
+ if (hasLower) strength += 1;
207
+ if (hasUpper) strength += 1;
208
+ if (hasNumber) strength += 1;
209
+ if (hasSpecial) strength += 1;
210
+
211
+ return Math.min(strength, 7);
212
+ }
213
+
214
+ // Actualizar la barra de fortaleza de contraseña
215
+ document.getElementById('password').addEventListener('input', function() {
216
+ const password = this.value;
217
+ const strength = checkPasswordStrength(password);
218
+ const meter = document.getElementById('strengthMeter');
219
+ const percentage = (strength / 7) * 100;
220
+
221
+ meter.style.width = percentage + '%';
222
+
223
+ // Cambiar color según la fortaleza
224
+ if (strength < 3) {
225
+ meter.style.background = '#ff4757';
226
+ } else if (strength < 5) {
227
+ meter.style.background = '#ffa502';
228
+ } else {
229
+ meter.style.background = '#2ed573';
230
+ }
231
+ });
232
+
233
+ document.getElementById('registerForm').addEventListener('submit', async (e) => {
234
+ e.preventDefault();
235
+
236
+ const username = document.getElementById('username').value;
237
+ const email = document.getElementById('email').value;
238
+ const password = document.getElementById('password').value;
239
+ const confirmPassword = document.getElementById('confirmPassword').value;
240
+ const errorMessage = document.getElementById('errorMessage');
241
+ const successMessage = document.getElementById('successMessage');
242
+
243
+ // Validar que las contraseñas coincidan
244
+ if (password !== confirmPassword) {
245
+ errorMessage.textContent = 'Las contraseñas no coinciden';
246
+ errorMessage.style.display = 'block';
247
+ return;
248
+ }
249
+
250
+ // Validar longitud mínima de contraseña
251
+ if (password.length < 6) {
252
+ errorMessage.textContent = 'La contraseña debe tener al menos 6 caracteres';
253
+ errorMessage.style.display = 'block';
254
+ return;
255
+ }
256
+
257
+ // Ocultar mensajes anteriores
258
+ errorMessage.style.display = 'none';
259
+ successMessage.style.display = 'none';
260
+
261
+ try {
262
+ const response = await fetch('/api/auth/register', {
263
+ method: 'POST',
264
+ headers: {
265
+ 'Content-Type': 'application/json',
266
+ },
267
+ body: JSON.stringify({ username, email, password })
268
+ });
269
+
270
+ const data = await response.json();
271
+
272
+ if (data.success) {
273
+ // Mostrar mensaje de éxito
274
+ successMessage.textContent = 'Registro exitoso. Redirigiendo al inicio de sesión...';
275
+ successMessage.style.display = 'block';
276
+
277
+ // Redirigir al login después de 2 segundos
278
+ setTimeout(() => {
279
+ window.location.href = '/login';
280
+ }, 2000);
281
+ } else {
282
+ // Mostrar mensaje de error
283
+ errorMessage.textContent = data.error || 'Error en el registro';
284
+ errorMessage.style.display = 'block';
285
+ }
286
+ } catch (error) {
287
+ console.error('Error en el registro:', error);
288
+ errorMessage.textContent = 'Error de conexión. Por favor, inténtalo de nuevo.';
289
+ errorMessage.style.display = 'block';
290
+ }
291
+ });
292
+ </script>
293
+ </body>
294
+ </html>
@@ -0,0 +1,47 @@
1
+ <!DOCTYPE html>
2
+ <html lang="es">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>{{title}}</title>
7
+ <link rel="stylesheet" href="/static/css/style.css">
8
+ </head>
9
+ <body>
10
+ <div class="header">
11
+ <h1>{{title}}</h1>
12
+ <nav>
13
+ <a href="/" class="button">Inicio</a>
14
+ <a href="/contact" class="button">Contacto</a>
15
+ </nav>
16
+ </div>
17
+
18
+ <div class="content">
19
+ <h2>Contáctanos</h2>
20
+
21
+ <form id="contact-form">
22
+ <div style="margin-bottom: 15px;">
23
+ <label for="name" style="display: block; margin-bottom: 5px;">Nombre:</label>
24
+ <input type="text" id="name" name="name" required style="width: 100%; padding: 8px; border: 1px solid #ccc; border-radius: 4px;">
25
+ </div>
26
+
27
+ <div style="margin-bottom: 15px;">
28
+ <label for="email" style="display: block; margin-bottom: 5px;">Email:</label>
29
+ <input type="email" id="email" name="email" required style="width: 100%; padding: 8px; border: 1px solid #ccc; border-radius: 4px;">
30
+ </div>
31
+
32
+ <div style="margin-bottom: 15px;">
33
+ <label for="message" style="display: block; margin-bottom: 5px;">Mensaje:</label>
34
+ <textarea id="message" name="message" required rows="5" style="width: 100%; padding: 8px; border: 1px solid #ccc; border-radius: 4px;"></textarea>
35
+ </div>
36
+
37
+ <button type="submit" class="button">Enviar Mensaje</button>
38
+ </form>
39
+ </div>
40
+
41
+ <div class="footer">
42
+ <p>&copy; 2026 Tienda JERK Framework. Todos los derechos reservados.</p>
43
+ </div>
44
+
45
+ <script src="/static/js/main.js"></script>
46
+ </body>
47
+ </html>
@@ -0,0 +1,39 @@
1
+ <!DOCTYPE html>
2
+ <html lang="es">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>{{title}}</title>
7
+ <link rel="stylesheet" href="/static/css/style.css">
8
+ </head>
9
+ <body>
10
+ <div class="header">
11
+ <h1>{{title}}</h1>
12
+ <nav>
13
+ <a href="/" class="button">Inicio</a>
14
+ <a href="/contact" class="button">Contacto</a>
15
+ </nav>
16
+ </div>
17
+
18
+ <div class="content">
19
+ <h2>Nuestros Productos</h2>
20
+
21
+ <div id="product-list">
22
+ {{foreach:products}}
23
+ <div class="product-card">
24
+ <h3>{{item.name}}</h3>
25
+ <p>{{item.description}}</p>
26
+ <p><strong>Precio:</strong> ${{item.price}}</p>
27
+ <p><strong>Categoría:</strong> {{item.category}}</p>
28
+ </div>
29
+ {{endforeach}}
30
+ </div>
31
+ </div>
32
+
33
+ <div class="footer">
34
+ <p>&copy; 2026 Tienda JERK Framework. Todos los derechos reservados.</p>
35
+ </div>
36
+
37
+ <script src="/static/js/main.js"></script>
38
+ </body>
39
+ </html>