mejoras
This commit is contained in:
+159
-37
@@ -448,6 +448,15 @@
|
||||
<input type="text" class="form-control border-0" placeholder="Buscar conversaciones..." id="search-input">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Filtro de conversaciones: Todos / No leídos -->
|
||||
<div style="padding:8px 12px; display:flex; gap:8px; align-items:center;">
|
||||
<select id="conversation-filter" class="form-select form-select-sm" style="width:auto;">
|
||||
<option value="all">Todos</option>
|
||||
<option value="unread">No leídos</option>
|
||||
</select>
|
||||
<small class="text-muted">Mostrar sólo conversaciones con mensajes no leídos</small>
|
||||
</div>
|
||||
|
||||
<div class="conversation-list" id="conversation-list">
|
||||
<div class="loading">
|
||||
@@ -488,6 +497,7 @@
|
||||
<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-secondary" id="mark-unread-btn" title="Marcar conversación como no leída" style="display:none;">Marcar no leído</button>
|
||||
<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>
|
||||
@@ -537,7 +547,14 @@
|
||||
this.currentConversationId = null;
|
||||
this.currentUserId = null;
|
||||
this.conversations = [];
|
||||
// Pagination state
|
||||
// Message pagination / loading state
|
||||
this.messageLimit = 50;
|
||||
this.loadingMessages = false;
|
||||
this.hasMoreMessages = false;
|
||||
this.earliestMessage = null; // timestamp of earliest loaded message
|
||||
// Filter state: 'all' or 'unread'
|
||||
this.conversationFilter = 'all';
|
||||
// Pagination state for conversation list
|
||||
this.conversationsPage = 1;
|
||||
this.conversationsLimit = 50;
|
||||
this.hasMoreConversations = true;
|
||||
@@ -692,6 +709,17 @@
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Filtro: Todos / No leídos
|
||||
const filterSelect = document.getElementById('conversation-filter');
|
||||
if (filterSelect) {
|
||||
filterSelect.value = this.conversationFilter;
|
||||
filterSelect.addEventListener('change', (e) => {
|
||||
this.conversationFilter = e.target.value || 'all';
|
||||
// reload conversations from first page
|
||||
this.loadConversations(1, false);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
setupAutoRefresh() {
|
||||
@@ -715,7 +743,7 @@
|
||||
const loadMoreBtn = document.getElementById('load-more-btn');
|
||||
if (loadMoreBtn) loadMoreBtn.disabled = true;
|
||||
try {
|
||||
const url = `api/get_conversations.php?page=${page}&limit=${this.conversationsLimit}`;
|
||||
const url = `api/get_conversations.php?page=${page}&limit=${this.conversationsLimit}&filter=${encodeURIComponent(this.conversationFilter)}`;
|
||||
const resp = await fetch(url);
|
||||
const data = await resp.json();
|
||||
console.log('Respuesta get_conversations:', data); // Debug
|
||||
@@ -769,10 +797,11 @@
|
||||
const container = document.getElementById('conversation-list');
|
||||
|
||||
if (this.conversations.length === 0) {
|
||||
const emptyMsg = this.conversationFilter === 'unread' ? 'No hay conversaciones no leídas' : 'No hay conversaciones aún';
|
||||
container.innerHTML = `
|
||||
<div class="text-center p-4">
|
||||
<i class="fas fa-comments fa-3x text-muted mb-3"></i>
|
||||
<p class="text-muted">No hay conversaciones aún</p>
|
||||
<p class="text-muted">${emptyMsg}</p>
|
||||
</div>
|
||||
`;
|
||||
return;
|
||||
@@ -901,10 +930,35 @@
|
||||
const btn = document.getElementById('bot-toggle');
|
||||
const holdIndicator = document.getElementById('hold-indicator');
|
||||
const releaseBtn = document.getElementById('release-hold-btn');
|
||||
const markUnreadBtn = document.getElementById('mark-unread-btn');
|
||||
|
||||
if (holdIndicator) {
|
||||
// Show different labels depending on state
|
||||
if (conv.on_hold) {
|
||||
if (markUnreadBtn) {
|
||||
markUnreadBtn.style.display = 'inline-block';
|
||||
markUnreadBtn.onclick = async () => {
|
||||
try {
|
||||
const resp = await fetch('api/mark_conversation_unread.php', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ user_id: userId })
|
||||
});
|
||||
if (resp.status === 401) {
|
||||
alert('Sesión expirada. Por favor inicie sesión de nuevo.');
|
||||
return;
|
||||
}
|
||||
const json = await resp.json();
|
||||
if (json && json.success) {
|
||||
// Recargar lista de conversaciones para reflejar cambios
|
||||
await this.loadConversations();
|
||||
alert('Conversación marcada como NO leída.');
|
||||
} else {
|
||||
alert('Error marcando conversación como no leída');
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Error marking conversation unread', e);
|
||||
alert('Error marcando conversación como no leída');
|
||||
}
|
||||
};
|
||||
}
|
||||
holdIndicator.textContent = 'EN ESPERA';
|
||||
holdIndicator.style.color = '#b85';
|
||||
holdIndicator.style.display = 'inline';
|
||||
@@ -1051,13 +1105,26 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Cargar mensajes
|
||||
await this.loadconversations(userId);
|
||||
// Cargar mensajes (con paginación)
|
||||
await this.loadMessages(userId, true);
|
||||
// Añadir listener para scroll arriba (cargar más historial)
|
||||
const chatContainer = document.getElementById('chat-conversations');
|
||||
if (chatContainer) {
|
||||
if (!chatContainer._infiniteScrollAdded) {
|
||||
chatContainer.addEventListener('scroll', async () => {
|
||||
if (chatContainer.scrollTop <= 60 && this.hasMoreMessages && !this.loadingMessages && this.currentUserId == userId) {
|
||||
await this.loadMessages(userId, false);
|
||||
}
|
||||
});
|
||||
chatContainer._infiniteScrollAdded = true;
|
||||
}
|
||||
}
|
||||
// Cargar respuestas rápidas
|
||||
await this.loadQuickReplies();
|
||||
}
|
||||
|
||||
async loadconversations(userId, showLoading = true) {
|
||||
// Compatibilidad: ahora delegamos en loadMessages
|
||||
if (showLoading) {
|
||||
document.getElementById('chat-conversations').innerHTML = `
|
||||
<div class="loading">
|
||||
@@ -1067,36 +1134,9 @@
|
||||
}
|
||||
|
||||
try {
|
||||
// Usar apiCall para incluir debug=true y manejo de auth/errores
|
||||
const data = await this.apiCall(`get_user_conversations.php?user_id=${userId}`);
|
||||
|
||||
let messages = [];
|
||||
if (!data) {
|
||||
throw new Error('No autorizado o error en la petición');
|
||||
}
|
||||
|
||||
if (Array.isArray(data)) {
|
||||
messages = data;
|
||||
} else if (data && data.success && Array.isArray(data.data)) {
|
||||
messages = data.data;
|
||||
} else if (Array.isArray(data.conversations)) {
|
||||
messages = data.conversations;
|
||||
}
|
||||
|
||||
this.conversations = messages;
|
||||
this.renderconversations();
|
||||
this.scrollToBottom();
|
||||
|
||||
// Marcar como leídos en el backend
|
||||
try {
|
||||
await this.apiCall('mark_conversation_read.php', { method: 'POST', body: { user_id: userId } });
|
||||
// Recargar lista de conversaciones para refrescar contadores
|
||||
await this.loadConversations();
|
||||
} catch (e) {
|
||||
console.error('Error marking conversation as read', e);
|
||||
}
|
||||
await this.loadMessages(userId, true);
|
||||
} catch (error) {
|
||||
console.error('Error loading conversations:', error);
|
||||
console.error('Error loading conversations via loadMessages:', error);
|
||||
document.getElementById('chat-conversations').innerHTML = `
|
||||
<div class="text-center p-4">
|
||||
<i class="fas fa-exclamation-triangle text-warning"></i>
|
||||
@@ -1106,6 +1146,88 @@
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cargar mensajes con paginación. Si initial=true, carga el bloque más reciente; si initial=false, carga mensajes anteriores (before=this.earliestMessage).
|
||||
*/
|
||||
async loadMessages(userId, initial = false) {
|
||||
if (this.loadingMessages) return;
|
||||
this.loadingMessages = true;
|
||||
const container = document.getElementById('chat-conversations');
|
||||
|
||||
// si cargamos más antiguos, preservar scroll
|
||||
let prevScrollHeight = container ? container.scrollHeight : 0;
|
||||
let prevScrollTop = container ? container.scrollTop : 0;
|
||||
|
||||
// indicador top cuando cargamos anteriores
|
||||
let topLoader = null;
|
||||
if (!initial && container) {
|
||||
container.insertAdjacentHTML('afterbegin', `<div class="loading loading-top" style="text-align:center; padding:8px; font-size:12px;">Cargando mensajes anteriores...</div>`);
|
||||
topLoader = container.querySelector('.loading-top');
|
||||
}
|
||||
|
||||
try {
|
||||
let url = `get_user_conversations.php?user_id=${userId}&limit=${this.messageLimit}`;
|
||||
if (!initial && this.earliestMessage) {
|
||||
url += `&before=${encodeURIComponent(this.earliestMessage)}`;
|
||||
}
|
||||
|
||||
const data = await this.apiCall(url);
|
||||
if (!data) throw new Error('No autorizado o error en la petición');
|
||||
|
||||
let messages = [];
|
||||
let hasMore = false;
|
||||
let earliest = null;
|
||||
if (data && data.success && Array.isArray(data.data)) {
|
||||
messages = data.data;
|
||||
hasMore = !!data.has_more;
|
||||
earliest = data.earliest || (messages[0] && messages[0].created_at) || null;
|
||||
} else if (Array.isArray(data)) {
|
||||
messages = data;
|
||||
}
|
||||
|
||||
if (initial) {
|
||||
this.conversations = messages;
|
||||
} else {
|
||||
// Prepend mensajes antiguos
|
||||
this.conversations = messages.concat(this.conversations);
|
||||
}
|
||||
|
||||
// Actualizar estado de paginación
|
||||
this.hasMoreMessages = hasMore;
|
||||
if (earliest) this.earliestMessage = earliest;
|
||||
|
||||
// Renderizar y ajustar scroll
|
||||
this.renderconversations();
|
||||
|
||||
if (initial) {
|
||||
this.scrollToBottom();
|
||||
} else if (container) {
|
||||
// Mantener posición: desplazar por la diferencia de heights
|
||||
const newScrollHeight = container.scrollHeight;
|
||||
container.scrollTop = newScrollHeight - prevScrollHeight + prevScrollTop;
|
||||
}
|
||||
|
||||
// remover loader top si existía
|
||||
if (topLoader && topLoader.parentNode) topLoader.remove();
|
||||
|
||||
// Marcar como leídos (comportamiento previo: marcar todos los entrantes como leídos al abrir)
|
||||
if (initial) {
|
||||
try {
|
||||
await this.apiCall('mark_conversation_read.php', { method: 'POST', body: { user_id: userId } });
|
||||
// Recargar lista de conversaciones para refrescar contadores
|
||||
await this.loadConversations();
|
||||
} catch (e) {
|
||||
console.error('Error marking conversation as read', e);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error en loadMessages:', error);
|
||||
} finally {
|
||||
this.loadingMessages = false;
|
||||
}
|
||||
}
|
||||
|
||||
renderconversations() {
|
||||
const container = document.getElementById('chat-conversations');
|
||||
|
||||
|
||||
Reference in New Issue
Block a user