up
This commit is contained in:
@@ -762,8 +762,11 @@ body {
|
|||||||
transform: translateX(-100%);
|
transform: translateX(-100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar.show {
|
.sidebar.show,
|
||||||
|
.sidebar.open {
|
||||||
transform: translateX(0);
|
transform: translateX(0);
|
||||||
|
box-shadow: 2px 0 20px rgba(0,0,0,0.2);
|
||||||
|
z-index: 1200;
|
||||||
}
|
}
|
||||||
|
|
||||||
.main-content {
|
.main-content {
|
||||||
|
|||||||
+73
-27
@@ -2245,39 +2245,85 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (btn) {
|
if (btn) {
|
||||||
// Mostrar como acciones de Atender / Finalizar
|
// Usar este botón como control único de Atender / Finalizar
|
||||||
btn.textContent = conv.bot_enabled ? 'Finalizar' : 'Atender';
|
btn.textContent = conv.in_service ? 'Finalizar' : 'Atender';
|
||||||
btn.title = conv.bot_enabled ? 'Finalizar atención' : 'Atender';
|
btn.title = conv.in_service ? 'Finalizar atención' : 'Atender';
|
||||||
btn.classList.toggle('btn-outline-danger', !conv.bot_enabled);
|
// Estilos según estado
|
||||||
btn.classList.toggle('btn-outline-secondary', conv.bot_enabled);
|
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)
|
// Mostrar el botón por defecto (se oculta en casos puntuales de on_hold si se desea)
|
||||||
if (conv.advisor_requested || conv.in_service || conv.on_hold) {
|
btn.style.display = 'inline-block';
|
||||||
btn.style.display = 'none';
|
btn.disabled = false;
|
||||||
} else {
|
|
||||||
btn.style.display = 'inline-block';
|
|
||||||
}
|
|
||||||
|
|
||||||
btn.onclick = async () => {
|
btn.onclick = async () => {
|
||||||
try {
|
try {
|
||||||
const resp = await fetch('api/set_bot_enabled.php', {
|
btn.disabled = true;
|
||||||
method: 'POST',
|
|
||||||
headers: { 'Content-Type': 'application/json' },
|
// Si ya está en servicio -> finalizar
|
||||||
body: JSON.stringify({ user_id: userId, enabled: conv.bot_enabled ? 0 : 1 })
|
if (conv.in_service) {
|
||||||
});
|
if (!confirm('¿Confirmas finalizar la atención?')) { btn.disabled = false; return; }
|
||||||
const json = await resp.json();
|
const resp = await this.apiCall('finish_attend.php', { body: { user_id: userId } });
|
||||||
if (json && json.success) {
|
if (resp && resp.success) {
|
||||||
conv.bot_enabled = !conv.bot_enabled;
|
showAlert('Finalizada la atención', 'success');
|
||||||
// update button label to match new state
|
conv.in_service = false;
|
||||||
btn.textContent = conv.bot_enabled ? 'Finalizar' : 'Atender';
|
conv.advisor_requested = 0;
|
||||||
btn.title = conv.bot_enabled ? 'Finalizar atención' : 'Atender';
|
conv.bot_enabled = true;
|
||||||
btn.classList.toggle('btn-outline-danger', !conv.bot_enabled);
|
if (holdIndicator) holdIndicator.style.display = 'none';
|
||||||
btn.classList.toggle('btn-outline-secondary', conv.bot_enabled);
|
|
||||||
|
// 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 {
|
} 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) {
|
} catch (err) {
|
||||||
console.error('Error toggling bot', e);
|
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
|
// Close sidebar on Escape
|
||||||
document.addEventListener('keydown', (e) => {
|
document.addEventListener('keydown', (e) => {
|
||||||
if (e.key === 'Escape') closeSidebar();
|
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}");
|
if (function_exists('writeLog')) writeLog('INFO', "Operator {$operatorId} finished attending for {$phoneNumber}, survey={$template}");
|
||||||
|
|
||||||
// Ensure consistent behavior: release hold / clear flags when finishing attend
|
// 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 {
|
try {
|
||||||
// Release hold silently to avoid duplicate notification after finishing attend
|
// Release hold silently to avoid duplicate notification after finishing attend
|
||||||
$this->releaseHold($phoneNumber, false);
|
// Send notification that conversation has been resumed, but do NOT auto-send the menu.
|
||||||
// Re-send main menu/topic so the user sees the menu after the advisor finishes
|
$this->releaseHold($phoneNumber, true);
|
||||||
try {
|
// Intentionally not calling showMainMenu or sending a 'conversation resumed' message here.
|
||||||
$this->showMainMenu($phoneNumber);
|
|
||||||
} catch (Exception $e) {
|
|
||||||
error_log('finishAttendConversation: showMainMenu failed: ' . $e->getMessage());
|
|
||||||
}
|
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
error_log('finishAttendConversation: releaseHold failed: ' . $e->getMessage());
|
error_log('finishAttendConversation: releaseHold failed: ' . $e->getMessage());
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user