/** * WhatsApp Bot Manager - JavaScript Simplificado * Versión sin librerías externas problemáticas */ class SimpleWhatsAppManager { constructor() { this.apiBaseUrl = './api/'; this.currentTab = 'dashboard'; this.init(); } init() { this.log('Iniciando sistema simplificado'); this.setupEventListeners(); this.loadDashboard(); } log(message, type = 'info') { const timestamp = new Date().toLocaleTimeString(); console.log(`[${timestamp}] [${type.toUpperCase()}] ${message}`); } setupEventListeners() { this.log('Configurando event listeners'); // Navegación de tabs - más defensiva const navLinks = document.querySelectorAll('.nav-link[data-tab]'); if (navLinks) { navLinks.forEach(link => { link.addEventListener('click', (e) => { e.preventDefault(); const tabName = link.getAttribute('data-tab'); if (tabName) { this.showTab(tabName); } }); }); } // Formularios this.setupFormListeners(); } setupFormListeners() { // Formulario de configuración const settingsForm = document.getElementById('settings-form'); if (settingsForm) { settingsForm.addEventListener('submit', (e) => { e.preventDefault(); this.saveSettings(); }); } // Formulario de envío de mensaje const sendForm = document.getElementById('send-message-form'); if (sendForm) { sendForm.addEventListener('submit', (e) => { e.preventDefault(); this.sendMessage(); }); } } showTab(tabName) { this.log(`Cambiando a tab: ${tabName}`); // Ocultar todas las pestañas const tabs = document.querySelectorAll('.tab-content'); if (tabs) { tabs.forEach(tab => tab.classList.remove('active')); } // Remover clase active de navegación const navLinks = document.querySelectorAll('.nav-link'); if (navLinks) { navLinks.forEach(link => link.classList.remove('active')); } // Mostrar pestaña seleccionada const targetTab = document.getElementById(tabName); if (targetTab) { targetTab.classList.add('active'); } // Activar enlace de navegación const activeLink = document.querySelector(`[data-tab="${tabName}"]`); if (activeLink) { activeLink.classList.add('active'); } this.currentTab = tabName; this.loadTabData(tabName); } loadTabData(tabName) { this.log(`Cargando datos para tab: ${tabName}`); switch (tabName) { case 'dashboard': this.loadDashboard(); break; case 'conversations': this.loadConversations(); break; case 'users': this.loadUsers(); break; case 'messages': this.loadMessages(); break; case 'templates': this.loadTemplates(); break; case 'settings': this.loadSettings(); break; default: this.log(`Tab no reconocido: ${tabName}`, 'warning'); } } 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', headers: { 'Content-Type': 'application/json', ...options.headers }, body: options.body ? JSON.stringify(options.body) : undefined }); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } 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); throw error; } } 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', headers: { 'Content-Type': 'application/json', ...options.headers }, body: options.body ? JSON.stringify(options.body) : undefined }); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } 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); throw error; } } async loadDashboard() { this.log('Cargando dashboard'); try { // Cargar estadísticas básicas const stats = await this.apiCall('manage_config.php?action=status'); this.updateStats(stats); } 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 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' } ]; elements.forEach(item => { const element = document.getElementById(item.id); if (element) { element.textContent = item.value; } }); } } 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); } } updateUsersList(users) { const container = document.getElementById('users-table'); if (!container) return; if (users.length === 0) { container.innerHTML = 'No hay usuarios registrados'; return; } 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} ${user.phone_number} ${user.name || 'Sin nombre'} ${user.status} ${user.current_menu || 'Sin menú'} ${formatDate} `; }); 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 || []); } else { this.showError('No se pudieron cargar las conversaciones'); } } catch (error) { this.showError('Error cargando conversaciones: ' + error.message); } } updateConversationsList(conversations) { const container = document.getElementById('conversations-table'); if (!container) return; if (conversations.length === 0) { container.innerHTML = 'No hay conversaciones'; return; } 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 += `
${conv.name || conv.phone_number}
${conv.phone_number}
${conv.content || 'Sin contenido'}
${conv.message_type || 'text'} ${conv.status || 'unknown'} ${formatDate} `; }); 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); } } updateSettingsForm(data) { if (!data) return; const fields = [ { id: 'whatsapp-token', value: data.token }, { id: 'phone-number-id', value: data.phone_number_id }, { id: 'webhook-token', value: data.webhook_verify_token }, { 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) { element.value = field.value; this.log(`Campo ${field.id} actualizado con valor: ${field.value}`); } else { this.log(`Campo ${field.id} no encontrado o sin valor`, 'warning'); } }); } async saveSettings() { this.log('Guardando configuraciones'); const settings = { token: document.getElementById('whatsapp-token').value, phone_number_id: document.getElementById('phone-number-id').value, webhook_verify_token: document.getElementById('webhook-token').value, 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); } } showError(message) { this.log(`Error: ${message}`, 'error'); this.showAlert(message, 'danger'); } showSuccess(message) { this.log(`Success: ${message}`, 'success'); this.showAlert(message, 'success'); } showAlert(message, type) { // Crear alerta temporal const alertDiv = document.createElement('div'); alertDiv.className = `alert alert-${type} alert-dismissible fade show position-fixed`; alertDiv.style.cssText = 'top: 20px; right: 20px; z-index: 9999; min-width: 300px;'; alertDiv.innerHTML = ` ${message} `; document.body.appendChild(alertDiv); // Auto-remover después de 5 segundos setTimeout(() => { if (alertDiv.parentNode) { alertDiv.parentNode.removeChild(alertDiv); } }, 5000); } 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); } } populateUsersSelect(users) { const select = document.getElementById('message-recipient'); if (!select) return; // Limpiar opciones existentes (excepto la primera) select.innerHTML = ''; // Agregar usuarios users.forEach(user => { const option = document.createElement('option'); option.value = user.id; option.textContent = `${user.name || user.phone_number} (${user.phone_number})`; select.appendChild(option); }); } populateTemplatesSelect(templates) { const select = document.getElementById('message-template'); if (!select) return; // Limpiar opciones existentes (excepto la primera) select.innerHTML = ''; // Agregar plantillas templates.forEach(template => { const option = document.createElement('option'); option.value = template.template_name; option.textContent = `${template.name} - ${template.category || 'Sin descripción'}`; select.appendChild(option); }); } 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); } } updateTemplatesList(templates) { const container = document.getElementById('templates-table'); if (!container) return; if (templates.length === 0) { container.innerHTML = 'No hay plantillas registradas'; return; } let html = ''; templates.forEach(template => { html += ` ${template.name} ${template.template_name} ${template.language_code || 'es'} ${template.category || 'utility'} ${template.status || 'pending'} `; }); container.innerHTML = html; } async saveTemplate() { this.log('Guardando plantilla'); try { const templateData = { name: document.getElementById('template-name').value, whatsapp_name: document.getElementById('template-whatsapp-name').value, 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); } } 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'); if (!userSelect.value) { 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) { const user = usersResponse.data.find(u => u.id == userId); if (user) { recipient = user.phone_number; } else { this.showError('Usuario no encontrado'); return; } } else { this.showError('Error obteniendo datos del usuario'); return; } } else { recipient = document.getElementById('manual-recipient').value; if (!recipient) { this.showError('Por favor ingresa un número de teléfono'); return; } } // Preparar mensaje según el tipo if (messageType === 'text') { const messageText = document.getElementById('message-text').value; if (!messageText) { this.showError('Por favor escribe un mensaje'); return; } messageData = { recipient: recipient, type: 'text', message: messageText }; } else { const templateSelect = document.getElementById('message-template'); if (!templateSelect.value) { 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 ? await this.apiCallReal('send_message.php', { method: 'POST', body: messageData }) : await this.apiCall('send_message.php', { 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); } } } // Inicializar cuando el DOM esté listo document.addEventListener('DOMContentLoaded', function() { console.log('DOM cargado, inicializando WhatsApp Manager...'); try { window.whatsappManager = new SimpleWhatsAppManager(); console.log('WhatsApp Manager inicializado correctamente'); } catch (error) { console.error('Error inicializando WhatsApp Manager:', error); } }); // Funciones globales para modales (compatibilidad con el HTML existente) 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(); } else { modalElement.style.display = 'block'; modalElement.classList.add('show'); } console.log('✅ Modal de plantilla abierto'); } catch (error) { console.error('❌ Error abriendo modal de plantilla:', error); } }; 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(); } else { modalElement.style.display = 'block'; modalElement.classList.add('show'); } console.log('✅ Modal de menú abierto'); } catch (error) { console.error('❌ Error abriendo modal de menú:', error); } }; // Función global para debugging window.debugAPI = async function(endpoint) { try { const manager = window.whatsappManager; if (manager) { const result = await manager.apiCall(endpoint); console.log('Debug API Result:', result); return result; } else { console.error('Manager no inicializado'); } } catch (error) { console.error('Debug API Error:', error); } }; // Función para ver conversación específica 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) { console.log('Editando usuario:', userId); alert(`Editar usuario ${userId} - Función en desarrollo`); }; // Función para eliminar usuario 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`); } }; // Funciones para plantillas window.showCreateTemplateModal = function() { const modal = new bootstrap.Modal(document.getElementById('createTemplateModal')); modal.show(); }; window.editTemplate = function(templateId) { console.log('Editando plantilla:', templateId); alert(`Editar plantilla ${templateId} - Función en desarrollo`); }; 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`); } }; // Hacer que app.saveTemplate() funcione window.app = { saveTemplate: function() { if (window.whatsappManager) { window.whatsappManager.saveTemplate(); } } }; // Funciones para el formulario de mensajes 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'; } else { existingGroup.style.display = 'block'; manualGroup.style.display = 'none'; } }; 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'; } else { textGroup.style.display = 'block'; templateGroup.style.display = 'none'; } }; // Función de diagnóstico window.runDiagnostic = function() { const resultsDiv = document.getElementById('diagnostic-results'); // Mostrar spinner de carga resultsDiv.innerHTML = `
Cargando...

Ejecutando diagnóstico...

`; fetch('./api/diagnose_whatsapp.php') .then(response => response.json()) .then(data => { if (data.success) { displayDiagnosticResults(data); } else { resultsDiv.innerHTML = `
Error: ${data.error || 'Error desconocido'}
`; } }) .catch(error => { console.error('Error en diagnóstico:', error); resultsDiv.innerHTML = `
Error de conexión: ${error.message}
`; }); }; function displayDiagnosticResults(data) { const resultsDiv = document.getElementById('diagnostic-results'); let html = `
Última verificación: ${data.timestamp}
Configuración
Phone Number ID ${data.config_status.phone_number_id ? '✓' : '✗'}
Access Token ${data.config_status.access_token ? '✓' : '✗'}
Webhook Token ${data.config_status.webhook_verify_token ? '✓' : '✗'}
Plantillas
${data.template_status.approved || 0}
Aprobadas
${data.template_status.pending || 0}
Pendientes
${data.template_status.rejected || 0}
Rechazadas
API WhatsApp
${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 += `
Recomendaciones
`; } html += '
'; resultsDiv.innerHTML = html; }