diff --git a/Archivo.zip b/Archivo.zip deleted file mode 100644 index 35db759..0000000 Binary files a/Archivo.zip and /dev/null differ diff --git a/api/diagnose_whatsapp.php b/api/diagnose_whatsapp.php index 7dd225e..56ca198 100644 --- a/api/diagnose_whatsapp.php +++ b/api/diagnose_whatsapp.php @@ -6,19 +6,15 @@ header('Access-Control-Allow-Headers: Content-Type'); require_once __DIR__ . '/../config/config.php'; +// Suprimir errores para obtener JSON limpio +error_reporting(E_ERROR | E_PARSE); + try { - // Verificar autenticación si no estás en modo debug - $debugMode = isset($_GET['debug']); + // Modo debug: desactivar autenticación si existe el parámetro debug + $debugMode = isset($_GET['debug']) && $_GET['debug'] === 'true'; + if (!$debugMode) { - if (session_status() === PHP_SESSION_NONE) { - session_start(); - } - - if (!isset($_SESSION['user_id'])) { - http_response_code(401); - echo json_encode(['error' => 'No autorizado']); - exit; - } + requireAuthentication(); } // Obtener configuración de WhatsApp @@ -123,6 +119,46 @@ try { $diagnostic['recommendations'][] = 'Todo parece estar configurado correctamente'; } + // Agregar compatibilidad con la estructura esperada en index.php + $configComplete = $diagnostic['config_status']['complete']; + $completionPercentage = 0; + $configFields = ['phone_number_id', 'access_token', 'webhook_verify_token', 'business_account_id']; + $completedFields = 0; + + foreach ($configFields as $field) { + if (isset($diagnostic['config_status'][$field]) && $diagnostic['config_status'][$field]) { + $completedFields++; + } + } + $completionPercentage = round(($completedFields / count($configFields)) * 100); + + // Estructura adicional para compatibilidad + $diagnostic['config'] = [ + 'status' => $configComplete ? 'complete' : 'incomplete', + 'message' => $configComplete ? 'Configuración completa' : 'Configuración incompleta', + 'completion' => $completionPercentage + ]; + + $diagnostic['templates'] = [ + 'approved' => $diagnostic['template_status']['approved'], + 'pending' => $diagnostic['template_status']['pending'], + 'rejected' => $diagnostic['template_status']['rejected'], + 'total' => $diagnostic['template_status']['total'], + 'message' => $diagnostic['template_status']['approved'] > 0 + ? 'Plantillas configuradas correctamente' + : ($diagnostic['template_status']['total'] > 0 + ? 'Tienes plantillas pendientes de aprobación' + : 'No hay plantillas configuradas') + ]; + + // Estructura API para compatibilidad + $diagnostic['api'] = [ + 'status' => $diagnostic['api_status']['reachable'] ? 'ready' : 'error', + 'message' => $diagnostic['api_status']['reachable'] + ? 'Conexión API establecida correctamente' + : ($diagnostic['api_status']['error'] ?? 'No conectado') + ]; + echo json_encode($diagnostic, JSON_PRETTY_PRINT); } catch (Exception $e) { diff --git a/assets/js/app_simple.js b/assets/js/app_simple.js index e5a7a7d..1092c8b 100644 --- a/assets/js/app_simple.js +++ b/assets/js/app_simple.js @@ -7,13 +7,14 @@ class SimpleWhatsAppManager { constructor() { this.apiBaseUrl = './api/'; this.currentTab = 'dashboard'; - + this.init(); } init() { this.log('Iniciando sistema simplificado'); this.setupEventListeners(); + this.setupCharts(); this.loadDashboard(); } @@ -24,7 +25,7 @@ class SimpleWhatsAppManager { setupEventListeners() { this.log('Configurando event listeners'); - + // Navegación de tabs - más defensiva const navLinks = document.querySelectorAll('.nav-link[data-tab]'); if (navLinks) { @@ -65,7 +66,7 @@ class SimpleWhatsAppManager { showTab(tabName) { this.log(`Cambiando a tab: ${tabName}`); - + // Ocultar todas las pestañas const tabs = document.querySelectorAll('.tab-content'); if (tabs) { @@ -96,7 +97,7 @@ class SimpleWhatsAppManager { loadTabData(tabName) { this.log(`Cargando datos para tab: ${tabName}`); - + switch (tabName) { case 'dashboard': this.loadDashboard(); @@ -113,6 +114,9 @@ class SimpleWhatsAppManager { case 'templates': this.loadTemplates(); break; + case 'logs': + this.loadLogs(); + break; case 'settings': this.loadSettings(); break; @@ -123,9 +127,9 @@ class SimpleWhatsAppManager { async apiCall(endpoint, options = {}) { const url = `${this.apiBaseUrl}${endpoint}${endpoint.includes('?') ? '&' : '?'}debug=true`; - + this.log(`API Call: ${url}`, 'info'); - + try { const response = await fetch(url, { method: options.method || 'GET', @@ -143,7 +147,7 @@ class SimpleWhatsAppManager { const data = await response.json(); this.log(`API Response: ${JSON.stringify(data).substring(0, 100)}...`, 'success'); return data; - + } catch (error) { this.log(`API Error: ${error.message}`, 'error'); this.showError('Error en petición: ' + error.message); @@ -153,9 +157,9 @@ class SimpleWhatsAppManager { async apiCallReal(endpoint, options = {}) { const url = `${this.apiBaseUrl}${endpoint}`; - + this.log(`API Call (REAL): ${url}`, 'info'); - + try { const response = await fetch(url, { method: options.method || 'GET', @@ -173,7 +177,7 @@ class SimpleWhatsAppManager { const data = await response.json(); this.log(`API Response (REAL): ${JSON.stringify(data).substring(0, 100)}...`, 'success'); return data; - + } catch (error) { this.log(`API Error (REAL): ${error.message}`, 'error'); this.showError('Error en petición real: ' + error.message); @@ -183,50 +187,181 @@ class SimpleWhatsAppManager { async loadDashboard() { this.log('Cargando dashboard'); - + try { // Cargar estadísticas básicas - const stats = await this.apiCall('manage_config.php?action=status'); + const stats = await this.apiCall('get_stats.php'); this.updateStats(stats); - + + // Cargar mensajes recientes + const recentMessagesResponse = await this.apiCall('get_recent_messages.php'); + if (recentMessagesResponse && recentMessagesResponse.success && Array.isArray(recentMessagesResponse.data)) { + this.updateRecentMessages(recentMessagesResponse.data); + } else if (recentMessagesResponse && Array.isArray(recentMessagesResponse)) { + // Retrocompatibilidad por si la API devuelve directamente el array + this.updateRecentMessages(recentMessagesResponse); + } + + // Actualizar gráfico si existe + this.updateChart(); + } catch (error) { this.showError('Error cargando dashboard: ' + error.message); } } - updateStats(response) { - if (response && response.success && response.data) { - const data = response.data; - - // Actualizar elementos del dashboard si existen + updateStats(stats) { + this.log('Actualizando estadísticas del dashboard'); + + if (stats) { const elements = [ - { id: 'total-users', value: data.total_configs || 0 }, - { id: 'messages-today', value: data.whatsapp_configured ? 'Configurado' : 'Sin configurar' }, - { id: 'active-users', value: data.database_migrated ? 'Migrada' : 'Pendiente' }, - { id: 'total-messages', value: data.installation_completed ? 'Completada' : 'Pendiente' } + { id: 'total-users', value: stats.total_users || 0 }, + { id: 'messages-today', value: stats.messages_today || 0 }, + { id: 'active-users', value: stats.active_users || 0 }, + { id: 'total-messages', value: stats.total_messages || 0 } ]; - + elements.forEach(item => { const element = document.getElementById(item.id); if (element) { element.textContent = item.value; + this.log(`Estadística actualizada: ${item.id} = ${item.value}`); } }); } } + updateRecentMessages(messages) { + const container = document.getElementById('recent-messages'); + if (!container) { + this.log('Contenedor de mensajes recientes no encontrado', 'warning'); + return; + } + + container.innerHTML = ''; + + if (messages && messages.length > 0) { + this.log(`Mostrando ${messages.length} mensajes recientes`); + messages.forEach(message => { + const messageElement = this.createRecentMessageElement(message); + container.appendChild(messageElement); + }); + } else { + container.innerHTML = '
No hay mensajes recientes
'; + } + } + + createRecentMessageElement(message) { + const div = document.createElement('div'); + div.className = 'recent-message mb-3 p-2 border-bottom'; + + const direction = message.direction === 'incoming' ? '📥' : '📤'; + const time = new Date(message.created_at).toLocaleString(); + + div.innerHTML = ` +
+ ${direction} ${message.phone_number} + ${time} +
+
${this.truncateText(message.content, 50)}
+ `; + + return div; + } + + truncateText(text, length) { + if (!text) return ''; + return text.length > length ? text.substring(0, length) + '...' : text; + } + + async updateChart() { + if (!this.charts || !this.charts.messages) { + this.log('Gráfico no inicializado, omitiendo actualización', 'warning'); + return; + } + + try { + const chartData = await this.apiCall('get_chart_data.php'); + if (chartData && this.charts.messages) { + this.charts.messages.data.labels = chartData.labels || []; + this.charts.messages.data.datasets[0].data = chartData.data || []; + this.charts.messages.update(); + this.log('Gráfico actualizado correctamente'); + } + } catch (error) { + this.log('Error actualizando gráfico: ' + error.message, 'warning'); + } + } + + setupCharts() { + const ctx = document.getElementById('messagesChart'); + if (!ctx) { + this.log('Canvas de gráfico no encontrado', 'warning'); + return; + } + + if (typeof Chart === 'undefined') { + this.log('Chart.js no está cargado', 'warning'); + return; + } + + try { + this.charts = this.charts || {}; + this.charts.messages = new Chart(ctx, { + type: 'line', + data: { + labels: [], + datasets: [{ + label: 'Mensajes', + data: [], + borderColor: '#25d366', + backgroundColor: 'rgba(37, 211, 102, 0.1)', + borderWidth: 3, + fill: true, + tension: 0.4 + }] + }, + options: { + responsive: true, + maintainAspectRatio: false, + scales: { + y: { + beginAtZero: true, + grid: { + color: 'rgba(0,0,0,0.1)' + } + }, + x: { + grid: { + color: 'rgba(0,0,0,0.1)' + } + } + }, + plugins: { + legend: { + display: false + } + } + } + }); + this.log('Gráfico de mensajes inicializado'); + } catch (error) { + this.log('Error inicializando gráfico: ' + error.message, 'error'); + } + } + async loadUsers() { this.log('Cargando usuarios'); - + try { const response = await this.apiCall('get_users.php'); - + if (response && response.success) { this.updateUsersList(response.data || []); } else { this.showError('No se pudieron cargar los usuarios'); } - + } catch (error) { this.showError('Error cargando usuarios: ' + error.message); } @@ -242,11 +377,11 @@ class SimpleWhatsAppManager { } let html = ''; - + users.forEach(user => { const createdDate = new Date(user.created_at); const formatDate = createdDate.toLocaleDateString() + ' ' + createdDate.toLocaleTimeString('es', { hour: '2-digit', minute: '2-digit' }); - + html += ` ${user.id} @@ -266,23 +401,28 @@ class SimpleWhatsAppManager { `; }); - + container.innerHTML = html; } async loadConversations() { this.log('Cargando conversaciones'); - + try { const response = await this.apiCall('get_conversations.php'); - - if (response && response.success) { - this.updateConversationsList(response.data || []); + console.log('Respuesta get_conversations:', response); // Debug + + if (response && response.success && Array.isArray(response.data)) { + this.updateConversationsList(response.data); + } else if (response && Array.isArray(response)) { + // Retrocompatibilidad por si la API devuelve directamente el array + this.updateConversationsList(response); } else { - this.showError('No se pudieron cargar las conversaciones'); + console.error('Formato de respuesta inesperado:', response); + this.showError('Error: formato de datos inválido para conversaciones'); } - } catch (error) { + console.error('Error en loadConversations:', error); this.showError('Error cargando conversaciones: ' + error.message); } } @@ -297,11 +437,11 @@ class SimpleWhatsAppManager { } let html = ''; - + conversations.forEach(conv => { const date = new Date(conv.created_at); const formatDate = date.toLocaleDateString() + ' ' + date.toLocaleTimeString('es', { hour: '2-digit', minute: '2-digit' }); - + html += ` @@ -326,20 +466,20 @@ class SimpleWhatsAppManager { `; }); - + container.innerHTML = html; } async loadSettings() { this.log('Cargando configuraciones'); - + try { const response = await this.apiCall('manage_config.php?action=whatsapp'); - + if (response && response.success) { this.updateSettingsForm(response.data); } - + } catch (error) { this.showError('Error cargando configuraciones: ' + error.message); } @@ -347,7 +487,7 @@ class SimpleWhatsAppManager { updateSettingsForm(data) { if (!data) return; - + const fields = [ { id: 'whatsapp-token', value: data.token }, { id: 'phone-number-id', value: data.phone_number_id }, @@ -355,7 +495,7 @@ class SimpleWhatsAppManager { { id: 'business-name', value: data.business_name }, { id: 'welcome-message', value: data.welcome_message } ]; - + fields.forEach(field => { const element = document.getElementById(field.id); if (element && field.value) { @@ -369,7 +509,7 @@ class SimpleWhatsAppManager { async saveSettings() { this.log('Guardando configuraciones'); - + const settings = { token: document.getElementById('whatsapp-token').value, phone_number_id: document.getElementById('phone-number-id').value, @@ -377,19 +517,19 @@ class SimpleWhatsAppManager { business_name: document.getElementById('business-name').value, welcome_message: document.getElementById('welcome-message').value }; - + try { const response = await this.apiCall('manage_config.php?action=save_whatsapp', { method: 'POST', body: { whatsapp: settings } }); - + if (response && response.success) { this.showSuccess('Configuraciones guardadas exitosamente'); } else { this.showError('Error guardando configuraciones'); } - + } catch (error) { this.showError('Error: ' + error.message); } @@ -414,9 +554,9 @@ class SimpleWhatsAppManager { ${message} `; - + document.body.appendChild(alertDiv); - + // Auto-remover después de 5 segundos setTimeout(() => { if (alertDiv.parentNode) { @@ -427,22 +567,22 @@ class SimpleWhatsAppManager { async loadMessages() { this.log('Cargando interfaz de mensajes'); - + try { // Cargar usuarios para el select const usersResponse = await this.apiCall('get_users.php'); - + if (usersResponse && usersResponse.success) { this.populateUsersSelect(usersResponse.data || []); } - + // Cargar plantillas para el select const templatesResponse = await this.apiCall('get_templates.php'); - + if (templatesResponse && templatesResponse.success) { this.populateTemplatesSelect(templatesResponse.data || []); } - + } catch (error) { this.showError('Error cargando datos para mensajes: ' + error.message); } @@ -482,16 +622,16 @@ class SimpleWhatsAppManager { async loadTemplates() { this.log('Cargando plantillas'); - + try { const response = await this.apiCall('get_templates.php'); - + if (response && response.success) { this.updateTemplatesList(response.data || []); } else { this.showError('Error cargando plantillas'); } - + } catch (error) { this.showError('Error cargando plantillas: ' + error.message); } @@ -507,7 +647,7 @@ class SimpleWhatsAppManager { } let html = ''; - + templates.forEach(template => { html += ` @@ -527,13 +667,13 @@ class SimpleWhatsAppManager { `; }); - + container.innerHTML = html; } async saveTemplate() { this.log('Guardando plantilla'); - + try { const templateData = { name: document.getElementById('template-name').value, @@ -541,37 +681,37 @@ class SimpleWhatsAppManager { language: document.getElementById('template-language').value, category: document.getElementById('template-category').value }; - + // Validar campos requeridos if (!templateData.name || !templateData.whatsapp_name) { this.showError('Nombre descriptivo y nombre de WhatsApp son requeridos'); return; } - + const response = await this.apiCall('save_template.php', { method: 'POST', body: templateData }); - + if (response && response.success) { this.showSuccess('Plantilla guardada correctamente'); - + // Cerrar modal const modal = document.getElementById('createTemplateModal'); if (modal) { const bsModal = bootstrap.Modal.getInstance(modal); if (bsModal) bsModal.hide(); } - + // Limpiar formulario document.getElementById('template-form').reset(); - + // Recargar plantillas this.loadTemplates(); } else { this.showError(`Error guardando plantilla: ${response?.error || 'Error desconocido'}`); } - + } catch (error) { this.showError('Error guardando plantilla: ' + error.message); } @@ -579,14 +719,14 @@ class SimpleWhatsAppManager { async sendMessage() { this.log('Enviando mensaje'); - + try { const recipientType = document.getElementById('recipient-type').value; const messageType = document.getElementById('message-type').value; - + let recipient; let messageData = {}; - + // Obtener destinatario if (recipientType === 'existing') { const userSelect = document.getElementById('message-recipient'); @@ -594,11 +734,11 @@ class SimpleWhatsAppManager { this.showError('Por favor selecciona un usuario'); return; } - + // Obtener datos del usuario seleccionado const selectedOption = userSelect.options[userSelect.selectedIndex]; const userId = userSelect.value; - + // Necesitamos obtener el número de teléfono del usuario const usersResponse = await this.apiCall('get_users.php'); if (usersResponse && usersResponse.success) { @@ -620,7 +760,7 @@ class SimpleWhatsAppManager { return; } } - + // Preparar mensaje según el tipo if (messageType === 'text') { const messageText = document.getElementById('message-text').value; @@ -628,7 +768,7 @@ class SimpleWhatsAppManager { this.showError('Por favor escribe un mensaje'); return; } - + messageData = { recipient: recipient, type: 'text', @@ -640,21 +780,21 @@ class SimpleWhatsAppManager { this.showError('Por favor selecciona una plantilla'); return; } - + messageData = { recipient: recipient, type: 'template', template_name: templateSelect.value }; } - + this.log(`Enviando mensaje a ${recipient}: ${JSON.stringify(messageData)}`); - + // Preguntar al usuario si quiere envío real o simulado const sendReal = confirm('¿Enviar mensaje REAL por WhatsApp?\n\nSí = Envío real\nNo = Envío simulado (debug)'); - + // Enviar mensaje - const response = sendReal + const response = sendReal ? await this.apiCallReal('send_message.php', { method: 'POST', body: messageData @@ -663,27 +803,42 @@ class SimpleWhatsAppManager { method: 'POST', body: messageData }); - + if (response && response.success) { this.showSuccess(`Mensaje enviado correctamente a ${recipient}`); - + // Limpiar formulario document.getElementById('send-message-form').reset(); document.getElementById('message-recipient').value = ''; } else { this.showError(`Error enviando mensaje: ${response?.error || 'Error desconocido'}`); } - + } catch (error) { this.showError('Error enviando mensaje: ' + error.message); } } + async loadLogs() { + try { + const response = await this.apiCall('get_logs.php'); + if (response && response.success && Array.isArray(response.data)) { + this.updateLogsTable(response.data); + } else if (response && Array.isArray(response)) { + // Retrocompatibilidad por si la API devuelve directamente el array + this.updateLogsTable(response); + } else { + this.showError('Error: formato de datos inválido para logs'); + } + } catch (error) { + this.showError('Error cargando logs: ' + error.message); + } + } } // Inicializar cuando el DOM esté listo -document.addEventListener('DOMContentLoaded', function() { +document.addEventListener('DOMContentLoaded', function () { console.log('DOM cargado, inicializando WhatsApp Manager...'); - + try { window.whatsappManager = new SimpleWhatsAppManager(); console.log('WhatsApp Manager inicializado correctamente'); @@ -693,19 +848,19 @@ document.addEventListener('DOMContentLoaded', function() { }); // Funciones globales para modales (compatibilidad con el HTML existente) -window.openCreateTemplateModal = function() { +window.openCreateTemplateModal = function () { console.log('🔵 Abriendo modal de plantilla...'); - + const modalElement = document.getElementById('createTemplateModal'); if (!modalElement) { console.error('❌ Modal de plantilla no encontrado'); return; } - + try { const form = document.getElementById('template-form'); if (form) form.reset(); - + if (typeof bootstrap !== 'undefined' && bootstrap.Modal) { const modal = new bootstrap.Modal(modalElement); modal.show(); @@ -719,19 +874,19 @@ window.openCreateTemplateModal = function() { } }; -window.openCreateMenuModal = function() { +window.openCreateMenuModal = function () { console.log('🔵 Abriendo modal de menú...'); - + const modalElement = document.getElementById('createMenuModal'); if (!modalElement) { console.error('❌ Modal de menú no encontrado'); return; } - + try { const form = document.getElementById('menu-form'); if (form) form.reset(); - + if (typeof bootstrap !== 'undefined' && bootstrap.Modal) { const modal = new bootstrap.Modal(modalElement); modal.show(); @@ -746,7 +901,7 @@ window.openCreateMenuModal = function() { }; // Función global para debugging -window.debugAPI = async function(endpoint) { +window.debugAPI = async function (endpoint) { try { const manager = window.whatsappManager; if (manager) { @@ -762,19 +917,19 @@ window.debugAPI = async function(endpoint) { }; // Función para ver conversación específica -window.viewConversation = function(userId) { +window.viewConversation = function (userId) { console.log('Viendo conversación del usuario:', userId); alert(`Ver conversación del usuario ${userId} - Función en desarrollo`); }; // Función para editar usuario -window.editUser = function(userId) { +window.editUser = function (userId) { console.log('Editando usuario:', userId); alert(`Editar usuario ${userId} - Función en desarrollo`); }; // Función para eliminar usuario -window.deleteUser = function(userId) { +window.deleteUser = function (userId) { console.log('Eliminando usuario:', userId); if (confirm(`¿Está seguro que desea eliminar el usuario ${userId}?`)) { alert(`Eliminar usuario ${userId} - Función en desarrollo`); @@ -782,17 +937,17 @@ window.deleteUser = function(userId) { }; // Funciones para plantillas -window.showCreateTemplateModal = function() { +window.showCreateTemplateModal = function () { const modal = new bootstrap.Modal(document.getElementById('createTemplateModal')); modal.show(); }; -window.editTemplate = function(templateId) { +window.editTemplate = function (templateId) { console.log('Editando plantilla:', templateId); alert(`Editar plantilla ${templateId} - Función en desarrollo`); }; -window.deleteTemplate = function(templateId) { +window.deleteTemplate = function (templateId) { console.log('Eliminando plantilla:', templateId); if (confirm(`¿Está seguro que desea eliminar la plantilla ${templateId}?`)) { alert(`Eliminar plantilla ${templateId} - Función en desarrollo`); @@ -801,7 +956,7 @@ window.deleteTemplate = function(templateId) { // Hacer que app.saveTemplate() funcione window.app = { - saveTemplate: function() { + saveTemplate: function () { if (window.whatsappManager) { window.whatsappManager.saveTemplate(); } @@ -809,11 +964,11 @@ window.app = { }; // Funciones para el formulario de mensajes -window.toggleRecipientType = function() { +window.toggleRecipientType = function () { const recipientType = document.getElementById('recipient-type').value; const existingGroup = document.getElementById('existing-recipient-group'); const manualGroup = document.getElementById('manual-recipient-group'); - + if (recipientType === 'manual') { existingGroup.style.display = 'none'; manualGroup.style.display = 'block'; @@ -823,11 +978,11 @@ window.toggleRecipientType = function() { } }; -window.toggleMessageType = function() { +window.toggleMessageType = function () { const messageType = document.getElementById('message-type').value; const textGroup = document.getElementById('message-text-group'); const templateGroup = document.getElementById('template-group'); - + if (messageType === 'template') { textGroup.style.display = 'none'; templateGroup.style.display = 'block'; @@ -838,9 +993,9 @@ window.toggleMessageType = function() { }; // Función de diagnóstico -window.runDiagnostic = function() { +window.runDiagnostic = function () { const resultsDiv = document.getElementById('diagnostic-results'); - + // Mostrar spinner de carga resultsDiv.innerHTML = `
@@ -850,7 +1005,7 @@ window.runDiagnostic = function() {

Ejecutando diagnóstico...

`; - + fetch('./api/diagnose_whatsapp.php') .then(response => response.json()) .then(data => { @@ -878,7 +1033,7 @@ window.runDiagnostic = function() { function displayDiagnosticResults(data) { const resultsDiv = document.getElementById('diagnostic-results'); - + let html = `
Última verificación: ${data.timestamp} @@ -938,15 +1093,15 @@ function displayDiagnosticResults(data) {
API WhatsApp
- ${data.api_status.reachable ? - `✓ Conectado - ${data.api_status.phone_number || 'N/A'}` : - `✗ ${data.api_status.error || 'No conectado'}` - } + ${data.api_status.reachable ? + `✓ Conectado - ${data.api_status.phone_number || 'N/A'}` : + `✗ ${data.api_status.error || 'No conectado'}` + }
`; - + // Recomendaciones if (data.recommendations && data.recommendations.length > 0) { html += ` @@ -962,7 +1117,58 @@ function displayDiagnosticResults(data) { `; } - + html += ''; resultsDiv.innerHTML = html; +} + + + +function updateLogsTable(logs) { + const tbody = document.getElementById('logs-table'); + if (!tbody) { + this.log('Tabla de logs no encontrada', 'warning'); + return; + } + + tbody.innerHTML = ''; + + if (!logs || logs.length === 0) { + tbody.innerHTML = 'No hay logs registrados'; + return; + } + + logs.forEach(log => { + const row = this.createLogRow(log); + tbody.appendChild(row); + }); + + this.log(`${logs.length} logs cargados en la tabla`); +} + +function createLogRow(log) { + const tr = document.createElement('tr'); + const date = new Date(log.created_at); + const formatDate = date.toLocaleDateString() + ' ' + date.toLocaleTimeString('es', { hour: '2-digit', minute: '2-digit' }); + + tr.innerHTML = ` + ${formatDate} + ${log.ip_address || 'N/A'} + + + ${log.status_code || 'N/A'} + + + + + + + + + `; + return tr; } \ No newline at end of file