up
This commit is contained in:
@@ -21,6 +21,8 @@ try {
|
||||
COALESCE(u.name, u.phone_number) AS name,
|
||||
u.phone_number,
|
||||
u.avatar_url,
|
||||
u.bot_enabled,
|
||||
u.on_hold,
|
||||
lm.message_id AS last_message_id,
|
||||
lm.content AS last_message,
|
||||
lm.direction AS direction,
|
||||
@@ -48,15 +50,17 @@ try {
|
||||
// Formatear datos para el frontend
|
||||
$conversations = array_map(function($conv) {
|
||||
return [
|
||||
'id' => intval($conv['id']),
|
||||
'user_id' => intval($conv['user_id']),
|
||||
'content' => $conv['content'] ?? '',
|
||||
'name' => $conv['name'] ?? $conv['phone_number'],
|
||||
'phone_number' => $conv['phone_number'],
|
||||
'avatar_url' => $conv['avatar_url'] ?? null,
|
||||
'last_message' => $conv['last_message'] ?? '',
|
||||
'last_time' => $conv['last_time'] ?? null,
|
||||
'direction' => $conv['direction'] ?? 'incoming',
|
||||
'message_type' => $conv['message_type'] ?? 'text',
|
||||
'status' => $conv['status'] ?? 'sent',
|
||||
'created_at' => $conv['created_at'],
|
||||
'phone_number' => $conv['phone_number'],
|
||||
'name' => $conv['name'] ?? $conv['phone_number']
|
||||
'unread_count' => intval($conv['unread_count'] ?? 0),
|
||||
'bot_enabled' => isset($conv['bot_enabled']) ? (bool)$conv['bot_enabled'] : true,
|
||||
'on_hold' => isset($conv['on_hold']) ? (bool)$conv['on_hold'] : false
|
||||
];
|
||||
}, $conversations);
|
||||
|
||||
|
||||
@@ -27,7 +27,8 @@ try {
|
||||
$approvedOnly = isset($_GET['approved_only']) && $_GET['approved_only'] == '1';
|
||||
$limit = isset($_GET['limit']) ? intval($_GET['limit']) : null;
|
||||
|
||||
$sql = "SELECT id, name, template_name, language_code, category, status, body_text, created_at FROM message_templates";
|
||||
// Ajuste: some DBs may not have body_text column; omit it to avoid SQL errors
|
||||
$sql = "SELECT id, name, template_name, language_code, category, status, created_at FROM message_templates";
|
||||
$params = [];
|
||||
|
||||
if ($approvedOnly) {
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
require_once '../config/config.php';
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
requireAuthentication();
|
||||
|
||||
try {
|
||||
$input = json_decode(file_get_contents('php://input'), true) ?: $_POST;
|
||||
$userId = isset($input['user_id']) ? intval($input['user_id']) : 0;
|
||||
if (!$userId) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['success' => false, 'error' => 'user_id required']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$db = Database::getInstance();
|
||||
$user = $db->fetch('SELECT phone_number FROM users WHERE id = :id', ['id' => $userId]);
|
||||
if (!$user) {
|
||||
http_response_code(404);
|
||||
echo json_encode(['success' => false, 'error' => 'User not found']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$db->update('users', ['on_hold' => 0], 'id = :id', ['id' => $userId]);
|
||||
|
||||
echo json_encode(['success' => true]);
|
||||
} catch (Exception $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
require_once '../config/config.php';
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
requireAuthentication();
|
||||
|
||||
try {
|
||||
$input = json_decode(file_get_contents('php://input'), true) ?: $_POST;
|
||||
$userId = isset($input['user_id']) ? intval($input['user_id']) : 0;
|
||||
$enabled = isset($input['enabled']) ? (int)$input['enabled'] : null;
|
||||
|
||||
if (!$userId || $enabled === null) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['success' => false, 'error' => 'user_id and enabled required']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$db = Database::getInstance();
|
||||
$db->update('users', ['bot_enabled' => $enabled], 'id = :id', ['id' => $userId]);
|
||||
|
||||
echo json_encode(['success' => true]);
|
||||
} catch (Exception $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
|
||||
}
|
||||
+69
-1
@@ -471,10 +471,16 @@
|
||||
<i class="fas fa-user"></i>
|
||||
</div>
|
||||
<div class="chat-header-info">
|
||||
<h6 id="chat-name">Usuario <button class="btn btn-sm btn-link" id="edit-user-btn" title="Editar usuario"><i class="fas fa-user-edit"></i></button></h6>
|
||||
<h6 id="chat-name">Usuario <button class="btn btn-sm btn-link" id="edit-user-btn" title="Editar usuario"><i class="fas fa-user-edit"></i></button>
|
||||
<span id="hold-indicator" style="display:none; margin-left:8px; color:#b85; font-weight:600">EN ESPERA</span>
|
||||
</h6>
|
||||
<small id="chat-phone">+1234567890</small>
|
||||
<div style="font-size:12px; margin-top:4px;"><button id="release-hold-btn" class="btn btn-sm btn-outline-primary" style="display:none">Liberar espera</button></div>
|
||||
</div>
|
||||
<div style="margin-left: auto; display:flex; gap:8px; align-items:center;">
|
||||
<div id="bot-toggle-container" style="display:flex;align-items:center;gap:6px;margin-right:8px;">
|
||||
<button class="btn btn-sm btn-outline-secondary" id="bot-toggle">Bot: On</button>
|
||||
</div>
|
||||
<button class="btn btn-sm btn-outline-danger" id="delete-conversation-btn" title="Eliminar conversación"><i class="fas fa-trash"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -728,6 +734,68 @@
|
||||
});
|
||||
document.querySelector(`[data-user-id="${userId}"]`)?.classList.add('active');
|
||||
|
||||
// Actualizar estado del toggle del bot según datos de la conversación
|
||||
const conv = this.conversations.find(c => c.user_id === userId);
|
||||
if (conv) {
|
||||
const btn = document.getElementById('bot-toggle');
|
||||
const holdIndicator = document.getElementById('hold-indicator');
|
||||
const releaseBtn = document.getElementById('release-hold-btn');
|
||||
|
||||
if (holdIndicator) {
|
||||
holdIndicator.style.display = conv.on_hold ? 'inline' : 'none';
|
||||
}
|
||||
|
||||
if (releaseBtn) {
|
||||
releaseBtn.style.display = conv.on_hold ? 'inline-block' : 'none';
|
||||
releaseBtn.onclick = async () => {
|
||||
try {
|
||||
const resp = await fetch('api/release_hold.php', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ user_id: userId })
|
||||
});
|
||||
const json = await resp.json();
|
||||
if (json && json.success) {
|
||||
conv.on_hold = false;
|
||||
holdIndicator.style.display = 'none';
|
||||
releaseBtn.style.display = 'none';
|
||||
await this.loadConversations();
|
||||
} else {
|
||||
alert('Error al liberar la espera');
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Error releasing hold', e);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if (btn) {
|
||||
btn.textContent = conv.bot_enabled ? 'Bot: On' : 'Bot: Off';
|
||||
btn.classList.toggle('btn-outline-danger', !conv.bot_enabled);
|
||||
btn.classList.toggle('btn-outline-secondary', conv.bot_enabled);
|
||||
btn.onclick = async () => {
|
||||
try {
|
||||
const resp = await fetch('api/set_bot_enabled.php', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ user_id: userId, enabled: conv.bot_enabled ? 0 : 1 })
|
||||
});
|
||||
const json = await resp.json();
|
||||
if (json && json.success) {
|
||||
conv.bot_enabled = !conv.bot_enabled;
|
||||
btn.textContent = conv.bot_enabled ? 'Bot: On' : 'Bot: Off';
|
||||
btn.classList.toggle('btn-outline-danger', !conv.bot_enabled);
|
||||
btn.classList.toggle('btn-outline-secondary', conv.bot_enabled);
|
||||
} else {
|
||||
alert('Error al cambiar el estado del bot');
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Error toggling bot', e);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Cargar mensajes
|
||||
await this.loadMessages(userId);
|
||||
// Cargar respuestas rápidas
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../config/config.php';
|
||||
$db = Database::getInstance();
|
||||
$col = $db->fetch("SHOW COLUMNS FROM users LIKE 'bot_enabled'");
|
||||
if ($col) {
|
||||
echo "Column bot_enabled already exists\n";
|
||||
exit(0);
|
||||
}
|
||||
try {
|
||||
$db->query("ALTER TABLE users ADD COLUMN bot_enabled TINYINT(1) NULL DEFAULT 1 AFTER bot_paused_until");
|
||||
echo "Added column bot_enabled\n";
|
||||
} catch (Exception $e) {
|
||||
echo "Failed to add bot_enabled: " . $e->getMessage() . "\n";
|
||||
exit(1);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../config/config.php';
|
||||
$db = Database::getInstance();
|
||||
try {
|
||||
$cols = $db->fetchAll('DESCRIBE message_templates');
|
||||
foreach ($cols as $c) echo $c['Field'] . ' => ' . $c['Type'] . PHP_EOL;
|
||||
} catch (Exception $e) {
|
||||
echo 'Error: ' . $e->getMessage() . PHP_EOL;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../config/config.php';
|
||||
require_once __DIR__ . '/../services/BotService.php';
|
||||
$db = Database::getInstance();
|
||||
$bot = new BotService();
|
||||
|
||||
$phone = '573012345678';
|
||||
$db->execute('DELETE FROM users WHERE phone_number = :p', ['p' => $phone]);
|
||||
$userId = $db->insert('users', ['phone_number' => $phone, 'status' => 'active', 'bot_enabled' => 0, 'welcome_sent_at' => date('Y-m-d H:i:s'), 'created_at' => date('Y-m-d H:i:s')]);
|
||||
$user = $db->fetch('SELECT * FROM users WHERE id = :id', ['id' => $userId]);
|
||||
|
||||
// Clear conversations
|
||||
$db->execute('DELETE FROM conversations WHERE user_id = :uid', ['uid' => $userId]);
|
||||
|
||||
// Send message while bot disabled
|
||||
$bot->processMessage($user, 'hola', 'text');
|
||||
$outs = $db->fetchAll("SELECT * FROM conversations WHERE user_id = :uid AND direction = 'outgoing'", ['uid' => $userId]);
|
||||
echo "Outgoing after disabled: " . count($outs) . "\n";
|
||||
|
||||
// Enable bot
|
||||
$db->update('users', ['bot_enabled' => 1], 'id = :id', ['id' => $userId]);
|
||||
$user2 = $db->fetch('SELECT * FROM users WHERE id = :id', ['id' => $userId]);
|
||||
$bot->processMessage($user2, 'hola', 'text');
|
||||
$outs2 = $db->fetchAll("SELECT * FROM conversations WHERE user_id = :uid AND direction = 'outgoing'", ['uid' => $userId]);
|
||||
echo "Outgoing after enabled: " . count($outs2) . "\n";
|
||||
|
||||
// Cleanup
|
||||
$db->execute('DELETE FROM conversations WHERE user_id = :uid', ['uid' => $userId]);
|
||||
$db->execute('DELETE FROM users WHERE id = :id', ['id' => $userId]);
|
||||
|
||||
echo "Done\n";
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
// Script de prueba para ejecutar api/get_templates.php en modo debug
|
||||
$_GET['debug'] = 'true';
|
||||
chdir(__DIR__ . '/../api');
|
||||
ob_start();
|
||||
try {
|
||||
include 'get_templates.php';
|
||||
} catch (Throwable $t) {
|
||||
echo "Throwable: " . $t->getMessage() . "\n";
|
||||
echo $t->getTraceAsString() . "\n";
|
||||
}
|
||||
$out = ob_get_clean();
|
||||
echo $out;
|
||||
@@ -51,6 +51,11 @@ class BotService {
|
||||
return;
|
||||
}
|
||||
|
||||
// Si el usuario ha desactivado el bot manualmente (toggle), no responder
|
||||
if (isset($user['bot_enabled']) && !$user['bot_enabled']) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Si el asesor ya respondió después del último mensaje del usuario, frenar al bot
|
||||
$lastIncoming = $this->db->fetch("SELECT created_at FROM conversations WHERE user_id = :uid AND direction = 'incoming' ORDER BY created_at DESC LIMIT 1", ['uid' => $user['id']]);
|
||||
$lastOutgoing = $this->db->fetch("SELECT created_at FROM conversations WHERE user_id = :uid AND direction = 'outgoing' ORDER BY created_at DESC LIMIT 1", ['uid' => $user['id']]);
|
||||
|
||||
Reference in New Issue
Block a user