up
This commit is contained in:
@@ -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
@@ -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 */ }
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user