up
This commit is contained in:
@@ -30,8 +30,10 @@ try {
|
||||
<title>WhatsApp Bot Manager</title>
|
||||
<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="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet" />
|
||||
<link href="https://cdn.jsdelivr.net/npm/select2-bootstrap-5-theme@1.3.0/dist/select2-bootstrap-5-theme.min.css" rel="stylesheet" />
|
||||
<link href="./assets/css/styles.css?v=11" rel="stylesheet">
|
||||
<link href="./assets/css/diagnostic.css?v=10" rel="stylesheet">
|
||||
<link href="./assets/css/diagnostic.css?v=11" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -45,7 +47,10 @@ try {
|
||||
<li><a href="#conversations" class="nav-link" data-tab="conversations"><i class="fas fa-comments"></i> Conversaciones <span id="conversations-count" class="sidebar-badge badge bg-danger" style="display:none; font-size:0.72rem; padding:0.15rem 0.4rem;">0</span></a></li>
|
||||
<li><a href="#users" class="nav-link" data-tab="users"><i class="fas fa-users"></i> Usuarios</a></li>
|
||||
<li><a href="#menus" class="nav-link" data-tab="menus"><i class="fas fa-list"></i> Menús</a></li>
|
||||
<li><a href="#admin_users" class="nav-link" data-tab="admin_users"><i class="fas fa-user-shield"></i> Usuarios del Sistema</a></li>
|
||||
<li><a href="#send_message" class="nav-link" data-tab="send_message"><i class="fas fa-paper-plane"></i> Enviar Mensaje</a></li>
|
||||
<li><a href="#broadcast" class="nav-link" data-tab="broadcast"><i class="fas fa-broadcast-tower"></i> Envío Masivo <span class="badge bg-success ms-1">NUEVO</span></a></li>
|
||||
<li><a href="scheduled_messages.php" class="nav-link"><i class="fas fa-clock"></i> Mensajes Programados</a></li>
|
||||
<li><a href="#templates" class="nav-link" data-tab="templates"><i class="fas fa-file-text"></i> Plantillas</a></li>
|
||||
<li><a href="#autoresponses" class="nav-link" data-tab="autoresponses"><i class="fas fa-robot"></i> Respuestas Auto</a></li>
|
||||
<li><a href="#system_config" class="nav-link" data-tab="system_config"><i class="fas fa-cog"></i> Configuración</a></li>
|
||||
@@ -236,6 +241,22 @@ try {
|
||||
</button>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<!-- Búsqueda de usuarios -->
|
||||
<div class="mb-3">
|
||||
<div class="input-group">
|
||||
<span class="input-group-text">
|
||||
<i class="fas fa-search"></i>
|
||||
</span>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
id="users-search"
|
||||
placeholder="Buscar por teléfono, nombre o email..."
|
||||
onkeyup="searchUsers()"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
@@ -254,6 +275,9 @@ try {
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Paginación -->
|
||||
<div id="users-pagination"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -290,6 +314,46 @@ try {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Admin Users Tab -->
|
||||
<div id="admin_users" class="tab-content">
|
||||
<div class="card">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<h5><i class="fas fa-user-shield"></i> Usuarios del Sistema</h5>
|
||||
<button class="btn btn-primary" onclick="showCreateAdminUserModal()">
|
||||
<i class="fas fa-plus"></i> Nuevo Usuario
|
||||
</button>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="alert alert-info mb-3">
|
||||
<i class="fas fa-info-circle"></i>
|
||||
Gestiona los usuarios administradores que tienen acceso al sistema.
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Usuario</th>
|
||||
<th>Nombre Completo</th>
|
||||
<th>Email</th>
|
||||
<th>Estado</th>
|
||||
<th>Último Acceso</th>
|
||||
<th>Fecha Creación</th>
|
||||
<th>Acciones</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="admin-users-table">
|
||||
<tr>
|
||||
<td colspan="7" class="text-center">
|
||||
<i class="fas fa-spinner fa-spin"></i> Cargando usuarios...
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- conversations Tab -->
|
||||
<div id="send_message" class="tab-content">
|
||||
<div class="row">
|
||||
@@ -336,10 +400,26 @@ try {
|
||||
</div>
|
||||
<div class="mb-3" id="template-group" style="display: none;">
|
||||
<label class="form-label">Plantilla</label>
|
||||
<select class="form-control" id="message-template">
|
||||
<select class="form-control" id="message-template" onchange="loadMessageTemplateDetails()">
|
||||
<option value="">Seleccionar plantilla...</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- Variables de la plantilla -->
|
||||
<div id="message-template-variables" class="mb-3" style="display: none;">
|
||||
<!-- Se llenarán dinámicamente -->
|
||||
</div>
|
||||
|
||||
<!-- Preview de la plantilla -->
|
||||
<div id="message-template-preview" class="mb-3" style="display: none;">
|
||||
<label class="form-label"><i class="fas fa-eye"></i> Vista Previa</label>
|
||||
<div class="card bg-light">
|
||||
<div class="card-body">
|
||||
<div id="message-preview-content"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<i class="fas fa-paper-plane"></i> Enviar Mensaje
|
||||
</button>
|
||||
@@ -348,33 +428,154 @@ try {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6" id="broadcast-section" style="display:none;">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5><i class="fas fa-broadcast-tower"></i> Mensaje Masivo (oculto)</h5>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Broadcast Tab -->
|
||||
<div id="broadcast" class="tab-content">
|
||||
<div class="row">
|
||||
<div class="col-lg-8 mx-auto">
|
||||
<div class="card shadow-lg">
|
||||
<div class="card-header bg-warning text-white">
|
||||
<h4 class="mb-0"><i class="fas fa-broadcast-tower"></i> Envío Masivo de Mensajes</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form id="broadcast-form">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Filtro de Usuarios</label>
|
||||
<select class="form-control" id="broadcast-filter">
|
||||
<option value="all">Todos los usuarios</option>
|
||||
<option value="active">Solo usuarios activos</option>
|
||||
<option value="recent">Usuarios recientes (30 días)</option>
|
||||
<div class="alert alert-success mb-4">
|
||||
<i class="fas fa-check-circle"></i>
|
||||
<strong>¡Envío Masivo Activo!</strong> Ahora puedes enviar mensajes a múltiples usuarios simultáneamente.
|
||||
</div>
|
||||
|
||||
<form id="broadcast-form" onsubmit="return handleBroadcastSubmit(event)">
|
||||
<div class="mb-4">
|
||||
<label class="form-label fw-bold">
|
||||
<i class="fas fa-filter"></i> Tipo de Selección
|
||||
</label>
|
||||
<select class="form-control form-control-lg" id="broadcast-selection-type" onchange="toggleBroadcastSelectionType()">
|
||||
<option value="filter">📋 Por filtro de usuarios</option>
|
||||
<option value="specific">👥 Usuarios específicos</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Mensaje</label>
|
||||
<textarea class="form-control" id="broadcast-message" rows="4" placeholder="Mensaje para envío masivo..."></textarea>
|
||||
|
||||
<!-- Filtro de usuarios -->
|
||||
<div class="mb-4" id="broadcast-filter-container">
|
||||
<label class="form-label fw-bold">
|
||||
<i class="fas fa-filter"></i> Filtro de Usuarios
|
||||
</label>
|
||||
<select class="form-control form-control-lg" id="broadcast-filter">
|
||||
<option value="all">📋 Todos los usuarios activos</option>
|
||||
<option value="active">🔥 Solo usuarios con conversaciones recientes (7 días)</option>
|
||||
<option value="recent">✨ Usuarios recientes (30 días)</option>
|
||||
</select>
|
||||
<small class="form-text text-muted">
|
||||
<i class="fas fa-info-circle"></i> Selecciona qué usuarios recibirán el mensaje
|
||||
</small>
|
||||
</div>
|
||||
<div class="alert alert-warning">
|
||||
<i class="fas fa-exclamation-triangle"></i>
|
||||
<strong>Cuidado:</strong> Este mensaje se enviará a múltiples usuarios.
|
||||
|
||||
<!-- Selección específica de usuarios -->
|
||||
<div class="mb-4" id="broadcast-users-container" style="display: none;">
|
||||
<label class="form-label fw-bold">
|
||||
<i class="fas fa-users"></i> Seleccionar Usuarios
|
||||
</label>
|
||||
<select class="form-control" id="broadcast-users" multiple="multiple">
|
||||
<!-- Opciones cargadas dinámicamente -->
|
||||
</select>
|
||||
<small class="form-text text-muted">
|
||||
<i class="fas fa-info-circle"></i> Selecciona uno o más usuarios para enviar el mensaje
|
||||
</small>
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
<label class="form-label fw-bold">
|
||||
<i class="fas fa-envelope"></i> Tipo de Mensaje
|
||||
</label>
|
||||
<select class="form-control form-control-lg" id="broadcast-message-type" onchange="toggleBroadcastMessageType()">
|
||||
<option value="text">📝 Mensaje de texto</option>
|
||||
<option value="template">📋 Plantilla de WhatsApp</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- Mensaje de texto -->
|
||||
<div class="mb-4" id="broadcast-text-container">
|
||||
|
||||
<label class="form-label fw-bold">
|
||||
<i class="fas fa-comment-dots"></i> Mensaje
|
||||
</label>
|
||||
<textarea
|
||||
class="form-control"
|
||||
id="broadcast-message"
|
||||
rows="6"
|
||||
placeholder="Escribe el mensaje que deseas enviar a todos los usuarios...
|
||||
|
||||
Ejemplo:
|
||||
¡Hola! 👋 Tenemos una promoción especial para ti..."
|
||||
maxlength="4096"></textarea>
|
||||
<div class="d-flex justify-content-between mt-2">
|
||||
<small class="form-text text-muted">
|
||||
<i class="fas fa-keyboard"></i> Máximo 4096 caracteres
|
||||
</small>
|
||||
<small class="form-text text-muted">
|
||||
<span id="char-count">0</span> / 4096
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Selección de plantilla -->
|
||||
<div class="mb-4" id="broadcast-template-container" style="display: none;">
|
||||
<label class="form-label fw-bold">
|
||||
<i class="fas fa-file-text"></i> Seleccionar Plantilla
|
||||
</label>
|
||||
<select class="form-control form-control-lg" id="broadcast-template" onchange="loadBroadcastTemplateDetails()">
|
||||
<option value="">-- Selecciona una plantilla --</option>
|
||||
</select>
|
||||
<small class="form-text text-muted">
|
||||
<i class="fas fa-info-circle"></i> Solo plantillas aprobadas
|
||||
</small>
|
||||
</div>
|
||||
|
||||
<!-- Variables de plantilla -->
|
||||
<div id="broadcast-template-variables" class="mb-4" style="display: none;">
|
||||
<!-- Variables dinámicas -->
|
||||
</div>
|
||||
|
||||
<!-- Vista previa de plantilla -->
|
||||
<div id="broadcast-template-preview" class="mb-4" style="display: none;">
|
||||
<label class="form-label fw-bold">
|
||||
<i class="fas fa-eye"></i> Vista Previa
|
||||
</label>
|
||||
<div class="alert alert-info" id="broadcast-preview-content">
|
||||
<!-- Contenido de vista previa -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-warning d-flex align-items-center">
|
||||
<i class="fas fa-exclamation-triangle fa-2x me-3"></i>
|
||||
<div>
|
||||
<strong>Importante:</strong> Este mensaje se enviará a múltiples usuarios.
|
||||
<br>Verifica cuidadosamente el contenido antes de enviar.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-grid">
|
||||
<button type="submit" class="btn btn-warning btn-lg">
|
||||
<i class="fas fa-broadcast-tower"></i> Enviar Mensaje Masivo
|
||||
</button>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-warning">
|
||||
<i class="fas fa-broadcast-tower"></i> Envío Masivo
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<div class="mt-4">
|
||||
<div class="card bg-light">
|
||||
<div class="card-body">
|
||||
<h6 class="fw-bold"><i class="fas fa-lightbulb text-warning"></i> Consejos para envío masivo:</h6>
|
||||
<ul class="mb-0 small">
|
||||
<li>Personaliza tu mensaje para que sea relevante</li>
|
||||
<li>Evita enviar mensajes muy frecuentes</li>
|
||||
<li>Respeta la ventana de 24 horas de WhatsApp</li>
|
||||
<li>Usa plantillas aprobadas para nuevos contactos</li>
|
||||
<li>Prueba con un grupo pequeño primero</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -386,11 +587,24 @@ 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" id="btn-new-template" onclick="showCreateTemplateModal()">
|
||||
<i class="fas fa-plus"></i> Nueva Plantilla
|
||||
</button>
|
||||
<div>
|
||||
<button class="btn btn-success" id="btn-sync-templates" onclick="syncTemplatesFromFacebook()">
|
||||
<i class="fas fa-sync-alt"></i> Sincronizar desde Facebook
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<!-- Mensaje informativo sobre creación de plantillas -->
|
||||
<div class="alert alert-info" role="alert">
|
||||
<h6 class="alert-heading"><i class="fas fa-info-circle"></i> ¿Cómo crear nuevas plantillas?</h6>
|
||||
<p class="mb-2">Las plantillas de WhatsApp deben crearse directamente en el Administrador de Meta Business.</p>
|
||||
<p class="mb-3">Una vez creadas y aprobadas por Meta, puedes sincronizarlas aquí usando el botón "Sincronizar desde Facebook".</p>
|
||||
<a href="https://business.facebook.com/latest/whatsapp_manager/message_templates?business_id=2144688622601603"
|
||||
class="btn btn-primary btn-sm" target="_blank" rel="noopener noreferrer">
|
||||
<i class="fas fa-external-link-alt"></i> Ir al Administrador de Plantillas de Meta
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
@@ -462,6 +676,11 @@ try {
|
||||
<label class="form-label">Phone Number ID</label>
|
||||
<input type="text" class="form-control" id="phone-number-id" placeholder="ID del número de teléfono">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Business Account ID (WABA ID)</label>
|
||||
<input type="text" class="form-control" id="business-account-id" placeholder="ID de la cuenta de WhatsApp Business">
|
||||
<small class="form-text text-muted">Necesario para sincronizar plantillas desde Facebook</small>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Webhook Verify Token</label>
|
||||
<input type="text" class="form-control" id="webhook-token" placeholder="Token de verificación del webhook">
|
||||
@@ -667,10 +886,104 @@ try {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal para crear/editar usuario administrador -->
|
||||
<div class="modal fade" id="adminUserModal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="adminUserModalLabel">
|
||||
<i class="fas fa-user-shield"></i> <span id="admin-user-modal-title">Nuevo Usuario</span>
|
||||
</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form id="admin-user-form">
|
||||
<input type="hidden" id="admin-user-id">
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Nombre de Usuario *</label>
|
||||
<input type="text" class="form-control" id="admin-username" required
|
||||
placeholder="usuario123">
|
||||
<small class="text-muted">Usado para iniciar sesión</small>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Nombre Completo</label>
|
||||
<input type="text" class="form-control" id="admin-fullname"
|
||||
placeholder="Juan Pérez">
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Email</label>
|
||||
<input type="email" class="form-control" id="admin-email"
|
||||
placeholder="usuario@ejemplo.com">
|
||||
</div>
|
||||
|
||||
<div class="mb-3" id="password-group">
|
||||
<label class="form-label">Contraseña *</label>
|
||||
<input type="password" class="form-control" id="admin-password"
|
||||
placeholder="Mínimo 6 caracteres">
|
||||
<small class="text-muted">Mínimo 6 caracteres</small>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
|
||||
<i class="fas fa-times"></i> Cancelar
|
||||
</button>
|
||||
<button type="button" class="btn btn-primary" onclick="saveAdminUser()">
|
||||
<i class="fas fa-save"></i> Guardar
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal para cambiar contraseña -->
|
||||
<div class="modal fade" id="changePasswordModal" tabindex="-1">
|
||||
<div class="modal-dialog modal-sm">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">
|
||||
<i class="fas fa-key"></i> Cambiar Contraseña
|
||||
</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<input type="hidden" id="change-password-user-id">
|
||||
<p class="mb-3">Usuario: <strong id="change-password-username"></strong></p>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Nueva Contraseña *</label>
|
||||
<input type="password" class="form-control" id="new-password"
|
||||
placeholder="Mínimo 6 caracteres" required>
|
||||
<small class="text-muted">Mínimo 6 caracteres</small>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Confirmar Contraseña *</label>
|
||||
<input type="password" class="form-control" id="confirm-password"
|
||||
placeholder="Repite la contraseña" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
|
||||
<i class="fas fa-times"></i> Cancelar
|
||||
</button>
|
||||
<button type="button" class="btn btn-primary" onclick="saveNewPassword()">
|
||||
<i class="fas fa-key"></i> Cambiar Contraseña
|
||||
</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/jquery@3.6.0/dist/jquery.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<script src="./assets/js/app_simple.js?v=14"></script>
|
||||
<script src="./assets/js/app_simple.js?v=18"></script>
|
||||
<script>
|
||||
// Función de diagnóstico mejorada
|
||||
function runDiagnostic() {
|
||||
@@ -1192,9 +1505,310 @@ try {
|
||||
}
|
||||
};
|
||||
|
||||
// ====== Funciones para Broadcast con Plantillas y Múltiples Usuarios ======
|
||||
|
||||
// Manejador del formulario de broadcast
|
||||
async function handleBroadcastSubmit(event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
console.log('Formulario de broadcast enviado');
|
||||
|
||||
// Validar que existe el manager
|
||||
if (!window.whatsappManager || !window.whatsappManager.sendBroadcast) {
|
||||
console.error('whatsappManager no disponible');
|
||||
alert('Error: Sistema no inicializado. Recarga la página.');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Validar variables de plantilla si se seleccionó plantilla
|
||||
const messageType = document.getElementById('broadcast-message-type').value;
|
||||
if (messageType === 'template') {
|
||||
const templateId = document.getElementById('broadcast-template').value;
|
||||
if (!templateId) {
|
||||
alert('Por favor selecciona una plantilla');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Validar que las variables requeridas estén llenas
|
||||
const varInputs = document.querySelectorAll('.broadcast-template-var');
|
||||
let hasEmpty = false;
|
||||
varInputs.forEach(input => {
|
||||
if (!input.value.trim()) {
|
||||
input.classList.add('is-invalid');
|
||||
hasEmpty = true;
|
||||
} else {
|
||||
input.classList.remove('is-invalid');
|
||||
}
|
||||
});
|
||||
|
||||
if (hasEmpty) {
|
||||
alert('Por favor completa todos los campos de variables de la plantilla');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Llamar al método del manager
|
||||
await window.whatsappManager.sendBroadcast();
|
||||
return false;
|
||||
}
|
||||
|
||||
function initializeBroadcastSelect2() {
|
||||
// Inicializar Select2 para usuarios con transport personalizado
|
||||
$('#broadcast-users').select2({
|
||||
theme: 'bootstrap-5',
|
||||
placeholder: 'Buscar y seleccionar usuarios...',
|
||||
allowClear: true,
|
||||
ajax: {
|
||||
transport: function (params, success, failure) {
|
||||
const searchTerm = params.data.term || '';
|
||||
const page = params.data.page || 1;
|
||||
|
||||
fetch(`api/get_users.php?search=${encodeURIComponent(searchTerm)}&page=${page}&limit=50`, {
|
||||
credentials: 'same-origin',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
success(data);
|
||||
} else {
|
||||
failure();
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error cargando usuarios:', error);
|
||||
failure();
|
||||
});
|
||||
},
|
||||
delay: 250,
|
||||
processResults: function (data, params) {
|
||||
params.page = params.page || 1;
|
||||
if (!data || !data.data) {
|
||||
return { results: [] };
|
||||
}
|
||||
return {
|
||||
results: data.data.map(user => ({
|
||||
id: user.id,
|
||||
text: `${user.name || 'Sin nombre'} (${user.phone_number})`
|
||||
})),
|
||||
pagination: {
|
||||
more: data.pagination && data.pagination.hasNext
|
||||
}
|
||||
};
|
||||
},
|
||||
cache: true
|
||||
},
|
||||
minimumInputLength: 0
|
||||
});
|
||||
|
||||
// Cargar plantillas aprobadas
|
||||
loadBroadcastTemplates();
|
||||
}
|
||||
|
||||
function toggleBroadcastSelectionType() {
|
||||
const selectionType = document.getElementById('broadcast-selection-type').value;
|
||||
const filterContainer = document.getElementById('broadcast-filter-container');
|
||||
const usersContainer = document.getElementById('broadcast-users-container');
|
||||
|
||||
if (selectionType === 'filter') {
|
||||
filterContainer.style.display = 'block';
|
||||
usersContainer.style.display = 'none';
|
||||
} else {
|
||||
filterContainer.style.display = 'none';
|
||||
usersContainer.style.display = 'block';
|
||||
}
|
||||
}
|
||||
|
||||
function toggleBroadcastMessageType() {
|
||||
const messageType = document.getElementById('broadcast-message-type').value;
|
||||
const textContainer = document.getElementById('broadcast-text-container');
|
||||
const templateContainer = document.getElementById('broadcast-template-container');
|
||||
|
||||
if (messageType === 'text') {
|
||||
textContainer.style.display = 'block';
|
||||
templateContainer.style.display = 'none';
|
||||
document.getElementById('broadcast-template-variables').style.display = 'none';
|
||||
document.getElementById('broadcast-template-preview').style.display = 'none';
|
||||
} else {
|
||||
textContainer.style.display = 'none';
|
||||
templateContainer.style.display = 'block';
|
||||
}
|
||||
}
|
||||
|
||||
async function loadBroadcastTemplates() {
|
||||
try {
|
||||
console.log('🔵 Cargando plantillas para broadcast...');
|
||||
|
||||
if (!window.whatsappManager) {
|
||||
console.error('❌ whatsappManager no está disponible');
|
||||
return;
|
||||
}
|
||||
|
||||
const response = await window.whatsappManager.apiCall('get_templates.php');
|
||||
console.log('Respuesta de get_templates:', response);
|
||||
|
||||
if (response && response.success && response.data) {
|
||||
const select = document.getElementById('broadcast-template');
|
||||
if (!select) {
|
||||
console.error('Elemento broadcast-template no encontrado');
|
||||
return;
|
||||
}
|
||||
|
||||
select.innerHTML = '<option value="">-- Selecciona una plantilla --</option>';
|
||||
|
||||
const approvedTemplates = response.data.filter(t =>
|
||||
t.status && (t.status.toUpperCase() === 'APPROVED' || t.status.toLowerCase() === 'approved')
|
||||
);
|
||||
console.log('Plantillas aprobadas encontradas:', approvedTemplates.length);
|
||||
|
||||
approvedTemplates.forEach(template => {
|
||||
const option = document.createElement('option');
|
||||
option.value = template.id;
|
||||
option.textContent = `${template.name} (${template.language_code || template.language || 'es'})`;
|
||||
option.dataset.templateId = template.id;
|
||||
select.appendChild(option);
|
||||
});
|
||||
|
||||
if (approvedTemplates.length === 0) {
|
||||
console.warn('No hay plantillas aprobadas disponibles');
|
||||
select.innerHTML = '<option value="">No hay plantillas aprobadas</option>';
|
||||
}
|
||||
} else {
|
||||
console.error('Respuesta inválida del API:', response);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error cargando plantillas:', error);
|
||||
}
|
||||
}
|
||||
|
||||
async function loadBroadcastTemplateDetails() {
|
||||
console.log('🔵 loadBroadcastTemplateDetails llamado');
|
||||
const select = document.getElementById('broadcast-template');
|
||||
const templateId = select.value;
|
||||
console.log('Template ID seleccionado:', templateId);
|
||||
|
||||
if (!templateId) {
|
||||
document.getElementById('broadcast-template-variables').style.display = 'none';
|
||||
document.getElementById('broadcast-template-preview').style.display = 'none';
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await window.whatsappManager.apiCall(`get_template_details.php?id=${templateId}`);
|
||||
console.log('✅ Detalles de plantilla:', response);
|
||||
|
||||
if (response && response.success) {
|
||||
const template = response.template || response.data;
|
||||
if (!template) {
|
||||
console.error('❌ No se encontró template en la respuesta');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('📋 Template data:', template);
|
||||
console.log('📋 Variables:', template.variables);
|
||||
|
||||
const variablesContainer = document.getElementById('broadcast-template-variables');
|
||||
|
||||
if (template.variables && template.variables.length > 0) {
|
||||
console.log(`✅ Se encontraron ${template.variables.length} variables`);
|
||||
let html = '<label class="form-label fw-bold"><i class="fas fa-edit"></i> Variables de la Plantilla</label>';
|
||||
|
||||
template.variables.forEach((variable, index) => {
|
||||
console.log(`Variable ${index}:`, variable);
|
||||
const placeholder = variable.example || `Valor para Variable ${variable.index}`;
|
||||
const label = variable.label || `Variable ${variable.index}`;
|
||||
|
||||
html += `
|
||||
<div class="mb-2">
|
||||
<label class="form-label small">${label}</label>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control broadcast-template-var"
|
||||
data-var="${variable.index}"
|
||||
data-placeholder="${variable.placeholder}"
|
||||
placeholder="${placeholder}"
|
||||
onkeyup="updateBroadcastPreview()"
|
||||
>
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
|
||||
console.log('📝 HTML generado para variables:', html);
|
||||
variablesContainer.innerHTML = html;
|
||||
variablesContainer.style.display = 'block';
|
||||
console.log('✅ Variables container mostrado');
|
||||
} else {
|
||||
console.log('⚠️ Template sin variables');
|
||||
variablesContainer.innerHTML = '<p class="text-muted small">Esta plantilla no tiene variables</p>';
|
||||
variablesContainer.style.display = 'block';
|
||||
}
|
||||
|
||||
updateBroadcastPreview();
|
||||
} else {
|
||||
console.error('❌ Respuesta sin success:', response);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('❌ Error cargando detalles de plantilla:', error);
|
||||
window.whatsappManager.showError('Error cargando plantilla');
|
||||
}
|
||||
}
|
||||
|
||||
async function updateBroadcastPreview() {
|
||||
const templateId = document.getElementById('broadcast-template').value;
|
||||
if (!templateId) return;
|
||||
|
||||
// Recolectar variables como array (por índice)
|
||||
const variablesArray = [];
|
||||
document.querySelectorAll('.broadcast-template-var').forEach(input => {
|
||||
const index = parseInt(input.dataset.var) - 1; // Convertir a índice de array (0-based)
|
||||
variablesArray[index] = input.value || `{{${input.dataset.var}}}`;
|
||||
});
|
||||
|
||||
try {
|
||||
const response = await window.whatsappManager.apiCall('preview_template.php', {
|
||||
method: 'POST',
|
||||
body: { template_id: templateId, parameters: variablesArray }
|
||||
});
|
||||
|
||||
if (response && response.success && response.preview) {
|
||||
const previewContainer = document.getElementById('broadcast-template-preview');
|
||||
const previewContent = document.getElementById('broadcast-preview-content');
|
||||
|
||||
// Usar el HTML pre-formateado del servidor
|
||||
previewContent.innerHTML = response.preview.html || response.preview.body.replace(/\n/g, '<br>');
|
||||
previewContainer.style.display = 'block';
|
||||
} else {
|
||||
console.error('Error en preview:', response);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error generando vista previa:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// ====== Fin de funciones de Broadcast ======
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
try { NotificationManager.init(); } catch(e) { console.error('NotificationManager init failed', e); }
|
||||
|
||||
// Inicializar Select2 para broadcast cuando el manager esté listo
|
||||
const waitForManager = setInterval(() => {
|
||||
if (window.whatsappManager) {
|
||||
clearInterval(waitForManager);
|
||||
console.log('Inicializando broadcast Select2...');
|
||||
try {
|
||||
initializeBroadcastSelect2();
|
||||
} catch(e) {
|
||||
console.error('Error inicializando broadcast Select2:', e);
|
||||
}
|
||||
}
|
||||
}, 100);
|
||||
|
||||
// Timeout de seguridad
|
||||
setTimeout(() => clearInterval(waitForManager), 5000);
|
||||
|
||||
// Sidebar toggle logic for responsive/mobile
|
||||
const sidebar = document.querySelector('.sidebar');
|
||||
const toggleBtn = document.getElementById('sidebar-toggle');
|
||||
|
||||
Reference in New Issue
Block a user