This commit is contained in:
Lizandro Guarnizo
2026-01-26 00:04:12 -05:00
parent b0107df7f2
commit 4b9c74e5d7
4 changed files with 90 additions and 35 deletions
+4 -1
View File
@@ -762,8 +762,11 @@ body {
transform: translateX(-100%);
}
.sidebar.show {
.sidebar.show,
.sidebar.open {
transform: translateX(0);
box-shadow: 2px 0 20px rgba(0,0,0,0.2);
z-index: 1200;
}
.main-content {
+73 -27
View File
@@ -2245,39 +2245,85 @@
}
if (btn) {
// Mostrar como acciones de Atender / Finalizar
btn.textContent = conv.bot_enabled ? 'Finalizar' : 'Atender';
btn.title = conv.bot_enabled ? 'Finalizar atención' : 'Atender';
btn.classList.toggle('btn-outline-danger', !conv.bot_enabled);
btn.classList.toggle('btn-outline-secondary', conv.bot_enabled);
// Usar este botón como control único de Atender / Finalizar
btn.textContent = conv.in_service ? 'Finalizar' : 'Atender';
btn.title = conv.in_service ? 'Finalizar atención' : 'Atender';
// Estilos según estado
btn.classList.toggle('btn-light', !!conv.in_service);
btn.classList.toggle('btn-outline-light', !conv.in_service);
// Hide bot toggle when advisor requested or in service or on hold (we expect attend/finish actions)
if (conv.advisor_requested || conv.in_service || conv.on_hold) {
btn.style.display = 'none';
} else {
btn.style.display = 'inline-block';
}
// Mostrar el botón por defecto (se oculta en casos puntuales de on_hold si se desea)
btn.style.display = 'inline-block';
btn.disabled = false;
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;
// update button label to match new state
btn.textContent = conv.bot_enabled ? 'Finalizar' : 'Atender';
btn.title = conv.bot_enabled ? 'Finalizar atención' : 'Atender';
btn.classList.toggle('btn-outline-danger', !conv.bot_enabled);
btn.classList.toggle('btn-outline-secondary', conv.bot_enabled);
btn.disabled = true;
// Si ya está en servicio -> finalizar
if (conv.in_service) {
if (!confirm('¿Confirmas finalizar la atención?')) { btn.disabled = false; return; }
const resp = await this.apiCall('finish_attend.php', { body: { user_id: userId } });
if (resp && resp.success) {
showAlert('Finalizada la atención', 'success');
conv.in_service = false;
conv.advisor_requested = 0;
conv.bot_enabled = true;
if (holdIndicator) holdIndicator.style.display = 'none';
// Intentar liberar hold en servidor por seguridad
try { await this.apiCall('release_hold.php', { body: { user_id: userId } }); } catch (e) { console.warn('release_hold after finish failed', e); }
// actualizar cache local
this._userStateCache = this._userStateCache || {};
this._userStateCache[userId] = { state: { in_service: false, advisor_requested: false, on_hold: false }, ts: Date.now() };
await this.loadConversations();
await this.loadMessages(userId, true);
} else {
throw new Error(resp && resp.error ? resp.error : 'Error finalizando');
}
} else {
alert('Error al cambiar el estado del bot');
// Tomar la atención
if (!confirm('¿Confirmas tomar la atención de esta conversación?')) { btn.disabled = false; return; }
const resp = await this.apiCall('attend.php', { body: { user_id: userId } });
if (resp && resp.success) {
showAlert('Atención iniciada', 'success');
conv.in_service = true;
conv.advisor_requested = 0;
conv.bot_enabled = false;
if (holdIndicator) {
holdIndicator.textContent = 'EN SERVICIO';
holdIndicator.style.color = '#28a745';
holdIndicator.style.display = 'inline';
}
// Add status message in chat to inform the user
try { this.showStatusMessageInChat(userId, 'Un asesor te está atendiendo'); } catch(e) { console.warn('showStatusMessageInChat failed', e); }
// actualizar cache local
this._userStateCache = this._userStateCache || {};
this._userStateCache[userId] = { state: { in_service: true, advisor_requested: false, on_hold: false }, ts: Date.now() };
await this.loadConversations();
await this.loadMessages(userId, true);
} else {
throw new Error(resp && resp.error ? resp.error : 'Error iniciando atención');
}
}
} catch (e) {
console.error('Error toggling bot', e);
} catch (err) {
console.error('Error toggling attend via main button', err);
showAlert('Error al cambiar estado de atención: ' + (err.message || err), 'danger');
} finally {
btn.disabled = false;
// Actualizar label y clases
btn.textContent = conv.in_service ? 'Finalizar' : 'Atender';
btn.title = conv.in_service ? 'Finalizar atención' : 'Atender';
btn.classList.toggle('btn-light', !!conv.in_service);
btn.classList.toggle('btn-outline-light', !conv.in_service);
// Re-render controls auxiliares
try { renderAttendControls(); } catch(e) { /* ignore */ }
}
};
}
+9
View File
@@ -1229,6 +1229,15 @@ try {
});
}
// Close sidebar when a nav item is selected (mobile UX improvement)
document.querySelectorAll('.nav-link[data-tab]').forEach(link => {
link.addEventListener('click', () => {
if (window.innerWidth < 992) {
closeSidebar();
}
});
});
// Close sidebar on Escape
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape') closeSidebar();
+4 -7
View File
@@ -1082,15 +1082,12 @@ class BotService {
if (function_exists('writeLog')) writeLog('INFO', "Operator {$operatorId} finished attending for {$phoneNumber}, survey={$template}");
// Ensure consistent behavior: release hold / clear flags when finishing attend
// Do NOT send the main menu nor notify the user that the conversation is resumed.
try {
// Release hold silently to avoid duplicate notification after finishing attend
$this->releaseHold($phoneNumber, false);
// Re-send main menu/topic so the user sees the menu after the advisor finishes
try {
$this->showMainMenu($phoneNumber);
} catch (Exception $e) {
error_log('finishAttendConversation: showMainMenu failed: ' . $e->getMessage());
}
// Send notification that conversation has been resumed, but do NOT auto-send the menu.
$this->releaseHold($phoneNumber, true);
// Intentionally not calling showMainMenu or sending a 'conversation resumed' message here.
} catch (Exception $e) {
error_log('finishAttendConversation: releaseHold failed: ' . $e->getMessage());
}