This commit is contained in:
Lizandro Guarnizo
2026-01-12 11:06:43 -05:00
parent ce12ac2cce
commit dd36ed6fe0
110 changed files with 20873 additions and 696 deletions
+218 -7
View File
@@ -13,6 +13,12 @@ if (!file_exists($installationLockFile)) {
require_once 'config/config.php';
// Verificar autenticación - redirigir al login si no está logueado
if (!isUserLoggedIn()) {
header('Location: login.php');
exit('Acceso denegado. <a href="login.php">Iniciar sesión</a>');
}
// Verificar conexión a la base de datos
try {
$db = Database::getInstance();
@@ -30,6 +36,7 @@ try {
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="./assets/css/styles.css" rel="stylesheet">
<link href="./assets/css/diagnostic.css" rel="stylesheet">
</head>
<body>
<!-- Sidebar -->
@@ -47,6 +54,8 @@ try {
<li><a href="#autoresponses" class="nav-link" data-tab="autoresponses"><i class="fas fa-robot"></i> Respuestas Auto</a></li>
<li><a href="#settings" class="nav-link" data-tab="settings"><i class="fas fa-cog"></i> Configuración</a></li>
<li><a href="#logs" class="nav-link" data-tab="logs"><i class="fas fa-file-alt"></i> Logs</a></li>
<li class="sidebar-divider"></li>
<li><a href="logout.php" class="nav-link logout-link" onclick="return confirm('¿Está seguro que desea cerrar sesión?')"><i class="fas fa-sign-out-alt"></i> Cerrar Sesión</a></li>
</ul>
</nav>
@@ -54,14 +63,23 @@ try {
<main class="main-content">
<!-- Header -->
<header class="content-header">
<h1><i class="fas fa-robot"></i> Sistema de Gestión WhatsApp Bot</h1>
<div>
<h1><i class="fas fa-robot"></i> Sistema de Gestión WhatsApp Bot</h1>
<small class="text-muted">
<i class="fas fa-user"></i> Conectado como <strong><?= htmlspecialchars(ADMIN_USERNAME) ?></strong>
| <i class="fas fa-clock"></i> Sesión desde: <?= date('H:i:s', $_SESSION['login_time'] ?? time()) ?>
</small>
</div>
<div class="header-actions">
<span class="status-indicator online">
<i class="fas fa-circle"></i> En línea
</span>
<button class="btn btn-primary" onclick="refreshData()">
<button class="btn btn-primary me-2" onclick="refreshData()">
<i class="fas fa-sync-alt"></i> Actualizar
</button>
<a href="logout.php" class="btn btn-outline-danger" onclick="return confirm('¿Está seguro que desea cerrar sesión?')">
<i class="fas fa-sign-out-alt"></i> Cerrar Sesión
</a>
</div>
</header>
@@ -291,14 +309,28 @@ try {
<div class="card-body">
<form id="send-message-form">
<div class="mb-3">
<label class="form-label">Tipo de Destinatario</label>
<select class="form-control" id="recipient-type" onchange="toggleRecipientType()">
<option value="existing">Usuario Registrado</option>
<option value="manual">Número Manual (Solo Plantillas)</option>
</select>
</div>
<div class="mb-3" id="existing-recipient-group">
<label class="form-label">Destinatario</label>
<select class="form-control" id="message-recipient" required>
<select class="form-control" id="message-recipient">
<option value="">Seleccionar usuario...</option>
</select>
</div>
<div class="mb-3" id="manual-recipient-group" style="display: none;">
<label class="form-label">Número de WhatsApp</label>
<input type="text" class="form-control" id="manual-recipient" placeholder="+57XXXXXXXXX">
<small class="form-text text-warning">
⚠️ Solo se pueden enviar plantillas aprobadas a números nuevos
</small>
</div>
<div class="mb-3">
<label class="form-label">Tipo de Mensaje</label>
<select class="form-control" id="message-type" required>
<select class="form-control" id="message-type" onchange="toggleMessageType()">
<option value="text">Texto</option>
<option value="template">Plantilla</option>
</select>
@@ -358,7 +390,7 @@ try {
<div class="card">
<div class="card-header d-flex justify-content-between align-items-center">
<h5><i class="fas fa-file-text"></i> Plantillas de Mensaje</h5>
<button class="btn btn-primary" onclick="showCreateTemplateModal()">
<button class="btn btn-primary" id="btn-new-template" onclick="showCreateTemplateModal()">
<i class="fas fa-plus"></i> Nueva Plantilla
</button>
</div>
@@ -460,6 +492,30 @@ try {
</div>
</div>
<div class="col-lg-4">
<!-- Panel de Diagnóstico -->
<div class="card mb-3">
<div class="card-header d-flex justify-content-between align-items-center">
<h5><i class="fas fa-stethoscope"></i> Diagnóstico</h5>
<button class="btn btn-sm btn-outline-primary" onclick="runDiagnostic()">
<i class="fas fa-play"></i> Ejecutar
</button>
</div>
<div class="card-body">
<div id="diagnostic-results">
<p class="text-muted">Haz clic en "Ejecutar" para verificar el estado del sistema</p>
</div>
<div class="mt-3" id="diagnostic-actions" style="display: none;">
<a href="approve_templates.html" class="btn btn-success btn-sm" target="_blank">
🔧 Solucionar Problema de Plantillas
</a>
<a href="GUIA_ERROR_PLANTILLAS.md" class="btn btn-info btn-sm" target="_blank">
📋 Ver Guía Completa
</a>
</div>
</div>
</div>
<!-- Información del Sistema -->
<div class="card">
<div class="card-header">
<h5><i class="fas fa-info-circle"></i> Información del Sistema</h5>
@@ -522,9 +578,164 @@ try {
</div>
</main>
<!-- Modal - Crear Plantilla -->
<div class="modal fade" id="createTemplateModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">📝 Nueva Plantilla de WhatsApp</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<form id="template-form">
<div class="mb-3">
<label class="form-label">Nombre descriptivo *</label>
<input type="text" class="form-control" id="template-name" required placeholder="ej: Bienvenida Cliente">
<small class="form-text text-muted">Nombre interno para identificar la plantilla</small>
</div>
<div class="mb-3">
<label class="form-label">Nombre en WhatsApp *</label>
<input type="text" class="form-control" id="template-whatsapp-name" required placeholder="ej: welcome_customer">
<small class="form-text text-muted">Debe coincidir exactamente con el nombre en WhatsApp Business Manager</small>
</div>
<div class="mb-3">
<label class="form-label">Idioma</label>
<select class="form-control" id="template-language">
<option value="es">Español</option>
<option value="en">English</option>
<option value="pt">Português</option>
</select>
</div>
<div class="mb-3">
<label class="form-label">Categoría</label>
<select class="form-control" id="template-category">
<option value="utility">Utilidad</option>
<option value="marketing">Marketing</option>
<option value="authentication">Autenticación</option>
</select>
</div>
<div class="alert alert-info">
<strong>⚠️ Importante:</strong> La plantilla debe ser creada y aprobada primero en WhatsApp Business Manager.
Este formulario solo registra plantillas ya existentes en WhatsApp.
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancelar</button>
<button type="button" class="btn btn-primary" onclick="app.saveTemplate()">Guardar Plantilla</button>
</div>
</div>
</div>
</div>
<!-- Modal de Crear Menú -->
<div class="modal fade" id="createMenuModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">📋 Nuevo Menú</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<form id="menu-form">
<div class="mb-3">
<label class="form-label">Nombre del Menú *</label>
<input type="text" class="form-control" id="menu-name" required placeholder="ej: Menú Principal">
</div>
<div class="mb-3">
<label class="form-label">Descripción</label>
<textarea class="form-control" id="menu-description" rows="3" placeholder="Descripción del menú (opcional)"></textarea>
</div>
<div class="alert alert-info">
<strong>️ Información:</strong> Después de crear el menú, podrás agregar opciones y configurar las respuestas.
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancelar</button>
<button type="button" class="btn btn-primary" onclick="saveNewMenu()">Crear Menú</button>
</div>
</div>
</div>
</div>
<!-- Scripts -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="./assets/js/app.js"></script>
<script src="./assets/js/app_simple.js"></script>
<script>
// Función de diagnóstico mejorada
function runDiagnostic() {
const resultsDiv = document.getElementById('diagnostic-results');
const actionsDiv = document.getElementById('diagnostic-actions');
resultsDiv.innerHTML = '<p class="text-muted"><i class="fas fa-spinner fa-spin"></i> Ejecutando diagnóstico...</p>';
fetch('/api/diagnose_whatsapp.php')
.then(response => response.json())
.then(data => {
if (data.success) {
let html = '<div class="diagnostic-report">';
// Configuración
html += `<div class="mb-3">
<h6><i class="fas fa-cog"></i> Configuración WhatsApp</h6>
<div class="alert alert-${data.config.status === 'complete' ? 'success' : 'warning'}">
${data.config.message} (${data.config.completion}% completa)
</div>
</div>`;
// Plantillas
const templateIssues = data.templates.approved === 0 && data.templates.pending > 0;
html += `<div class="mb-3">
<h6><i class="fas fa-file-alt"></i> Estado de Plantillas</h6>
<div class="alert alert-${templateIssues ? 'danger' : 'success'}">
${data.templates.message}
<br><small>Aprobadas: ${data.templates.approved} | Pendientes: ${data.templates.pending}</small>
</div>
</div>`;
// API
html += `<div class="mb-3">
<h6><i class="fas fa-plug"></i> Conectividad API</h6>
<div class="alert alert-${data.api.status === 'ready' ? 'success' : 'warning'}">
${data.api.message}
</div>
</div>`;
// Recomendaciones
if (data.recommendations && data.recommendations.length > 0) {
html += `<div class="mb-3">
<h6><i class="fas fa-lightbulb"></i> Recomendaciones</h6>
<ul class="list-unstyled">`;
data.recommendations.forEach(rec => {
html += `<li class="mb-1"><i class="fas fa-arrow-right text-primary"></i> ${rec}</li>`;
});
html += `</ul></div>`;
}
html += '</div>';
resultsDiv.innerHTML = html;
// Mostrar botones de acción si hay problemas con plantillas
if (templateIssues) {
actionsDiv.style.display = 'block';
} else {
actionsDiv.style.display = 'none';
}
} else {
resultsDiv.innerHTML = `<div class="alert alert-danger">Error: ${data.message}</div>`;
actionsDiv.style.display = 'none';
}
})
.catch(error => {
console.error('Error:', error);
resultsDiv.innerHTML = '<div class="alert alert-danger">Error de conectividad</div>';
actionsDiv.style.display = 'none';
});
}
</script>
</body>
</html>
</html>