const listView = document.getElementById('list-view'); const observationView = document.getElementById('obs-view'); // Novos elementos do layout redesenhado const queueTableBody = document.getElementById('queue-table-body'); const queueEmpty = document.getElementById('queue-empty'); const queueCount = document.getElementById('queue-count'); const currentCard = document.getElementById('current-card'); const noCurrentCard = document.getElementById('no-current'); const cardTicket = document.getElementById('card-ticket'); const cardStatusBadge = document.getElementById('card-status-badge'); const cardClientName = document.getElementById('card-client-name'); const cardService = document.getElementById('card-service'); const cardType = document.getElementById('card-type'); const nextButton = document.getElementById('next-button'); const recallButton = document.getElementById('recall-button'); const forwardButton = document.getElementById('forward-button'); const logoutButton = document.getElementById('logout-button'); const observationText = document.getElementById('observation-text'); const saveButton = document.getElementById('save-button'); const selectedItemNameSpan = document.getElementById('selected-item-name'); const idAtend = document.getElementById('idAtend'); const counterStart = document.getElementById('counter-start'); // Elementos do Modal de Encaminhamento const forwardView = document.getElementById('forward-view'); const operatorsList = document.getElementById('operators-list'); const closeForward = document.getElementById('close-forward'); const forwardTicketSpan = document.getElementById('forward-ticket'); let currentData = []; let selectedItemId = null; let selectedItemName = ''; // =========================== // FLAG que trava o ID do atendimento chamado. // Quando o call-next retorna e define o atendimento atual, // este flag impede que atualizações da fila sobrescrevam o selectedItemId. // =========================== let calledAtendimentoData = null; // Guarda os dados completos do atendimento chamado window.electronAPI.onLoadData((data) => { // Se já estiver em atendimento, ignora atualizações da lista para evitar flickering no botão if (localStorage.getItem('atendimentoAtual')) { return; } if (!data) { return; } populateQueueTable(data); }); async function initializeSocket() { if (typeof window.electronAPI === 'undefined' || !window.electronAPI.getPusherConfig) { console.error('electronAPI not available or getPusherConfig method missing.'); return; } const config = await window.electronAPI.getPusherConfig(); let host = config.host; const tenantId = localStorage.getItem('tenantId'); const token = localStorage.getItem('authToken'); //! checa se ja tem o colabId e o tenantId if (tenantId && token) { // Conexão Socket.io adaptada do Pusher const socket = io(host, { auth: { token }, extraHeaders: { 'x-tenant-id': tenantId } }); socket.on('connect', () => { console.log('Socket.io conectado ao host: ', host); }); // Evento que substitui o bind do Pusher socket.on('queueUpdate', (data) => { console.log('Notificação de fila recebida:', data); // Avisa o processo principal que houve mudança. // O main vai buscar a lista completa e atualizar todas as janelas. window.electronAPI.updateQueue(); }); socket.on('error', (err) => { console.error('Socket.io connection error: ', err); }); } else { console.warn('User not authenticated or tenantId not available. WebSocket not connected.'); } } initializeSocket(); //chama o proximo da fila ao abrir a janela de atendimentos window.electronAPI.selectAtendID((data) => { nextButton.disabled = true; if (!data) { showNoCurrentCard('Ninguém aguardando atendimento'); return; } // Trava os dados do atendimento chamado para que atualizações da fila // NÃO sobrescrevam quem foi chamado. calledAtendimentoData = data; selectedItemId = data._id ?? null; selectedItemName = data.clientName ?? ''; // Atualiza a tabela da fila (sem afetar o card atual) // populateQueueTable já NÃO mexe no selectedItemId quando calledAtendimentoData está travado showListView(); // Mostra o card do atendimento chamado showCurrentCard(data); }); window.electronAPI.showObservation(() => { window.electronAPI.iniciaAtendimento(selectedItemId); showObservationView(); // Muda para a tela de observação }); // Função para popular a tabela da fila function populateQueueTable(proximos) { const atendimentoEmAndamentoId = localStorage.getItem('atendimentoAtual'); const atendimentoEmAndamentoNome = localStorage.getItem('atendimentoAtualNome'); if (atendimentoEmAndamentoId) { // Em atendimento: mostra card de atendimento no painel direito queueTableBody.innerHTML = ''; queueCount.textContent = '0'; queueEmpty.style.display = 'flex'; document.querySelector('.queue-table').style.display = 'none'; // Mostra card como "Atendendo" currentCard.style.display = 'flex'; noCurrentCard.style.display = 'none'; cardTicket.textContent = ''; cardStatusBadge.textContent = 'Atendendo'; cardStatusBadge.className = 'card-badge badge-atendendo'; cardClientName.textContent = (atendimentoEmAndamentoNome || '').toUpperCase(); cardService.textContent = ''; cardType.textContent = ''; nextButton.disabled = true; recallButton.disabled = true; forwardButton.disabled = true; return; } // Se não vier dados por parâmetro, tenta pegar do localStorage (fallback) if (!Array.isArray(proximos)) { let datastorage = localStorage.getItem('proximos'); proximos = JSON.parse(datastorage || '[]'); } // Limpa e popula a tabela queueTableBody.innerHTML = ''; if (!proximos || proximos.length === 0) { queueEmpty.style.display = 'flex'; document.querySelector('.queue-table').style.display = 'none'; queueCount.textContent = '0'; } else { queueEmpty.style.display = 'none'; document.querySelector('.queue-table').style.display = 'table'; queueCount.textContent = proximos.length; proximos.forEach((item, index) => { const tr = document.createElement('tr'); const isPreferencial = item.ticketNumber && item.ticketNumber.startsWith('P'); tr.innerHTML = `
Carregando atendentes...
'; const response = await window.electronAPI.getOperators(); if (response.success && response.operators) { operatorsList.innerHTML = ''; response.operators.forEach(op => { const item = document.createElement('div'); item.className = 'operator-item'; item.textContent = op.name; item.onclick = () => { if (confirm(`Encaminhar para ${op.name}?`)) { window.electronAPI.encaminharAtendimento({ itemId: calledAtendimentoData._id, collaboratorId: op._id }); forwardView.style.display = 'none'; // Limpa o atendimento atual pois foi encaminhado localStorage.removeItem('atendimentoAtual'); localStorage.removeItem('atendimentoAtualNome'); calledAtendimentoData = null; selectedItemId = null; showListView(); } }; operatorsList.appendChild(item); }); if (response.operators.length === 0) { operatorsList.innerHTML = 'Nenhum outro atendente disponível.
'; } } else { operatorsList.innerHTML = `${response.message || 'Erro ao carregar atendentes.'}
`; } } }); closeForward.addEventListener('click', () => { forwardView.style.display = 'none'; }); logoutButton.addEventListener('click', () => { window.electronAPI.logoutApp(); }); // // // Evento do botão "Salvar" saveButton.addEventListener('click', () => { const observation = observationText.value; if (selectedItemId !== null) { // Limpa o estado de atendimento localStorage.removeItem('atendimentoAtual'); localStorage.removeItem('atendimentoAtualNome'); window.electronAPI.atendimentoFinalizado(); // Limpa o travamento calledAtendimentoData = null; window.electronAPI.saveObservation({ itemId: selectedItemId, observation: observation }); window.location.reload(); } });