adicionado correções ao app colab

This commit is contained in:
Eder Moraes 2026-04-27 02:12:42 -03:00
parent 99b34b2871
commit d12f38fbaf
3 changed files with 131 additions and 99 deletions

136
main.js
View File

@ -100,7 +100,7 @@ async function fetchDataFromAPI() {
//! as outras é o websockt que solicita a chamada de requisições em busca de alterações
const updData = setInterval(() => {
getDataAndUpdateFloatingBtn();
}, 3000);
}, 30000);
const updVersion = setTimeout(() => {
if (pjson.isBuildNow) {
@ -110,16 +110,17 @@ async function fetchDataFromAPI() {
}
async function getFirstData() {
const token = await getAuthToken();
const colabId = await floatingWin.webContents.executeJavaScript("localStorage.getItem('idOperator')")
const colabId = await getSelectedOperatorId();
const tenantId = await getTenantId();
const url = apiUrl + 'attendance/next-in-line/' + colabId;
//! checa se o token e o colabId existem
if (!token && !colabId) { console.warn("Token or colabId not found in localStorage. API requests will not be made."); return; }
if (!token || !colabId) {
console.warn("Token or colabId not found. Skipping API request.");
return [];
}
//! faz o request
return new Promise((resolve) => {
const request = net.request({
method: 'GET',
url: url,
@ -130,48 +131,59 @@ async function getFirstData() {
}
});
//! busca pela resposta
request.on('response', (response) => {
let rawData = '';
response.on('data', (chunk) => { rawData += chunk; });
response.on('end', () => {
response.on('end', async () => {
try {
const parsedData = JSON.parse(rawData);
let proximos = Array.isArray(parsedData) ? parsedData : [];
if (response.statusCode === 200) {
floatingWin.webContents.executeJavaScript("localStorage.setItem('proximos','" + JSON.stringify(proximos) + "')");
let count = proximos.length;
floatingWin.webContents.send('update-count', count);
const proximosStr = JSON.stringify(proximos);
// Sincroniza o localStorage de todas as janelas importantes
const updateStorageScript = `localStorage.setItem('proximos', ${JSON.stringify(proximosStr)})`;
if (floatingWin && !floatingWin.isDestroyed()) {
floatingWin.webContents.executeJavaScript(updateStorageScript);
floatingWin.webContents.send('update-count', proximos.length);
}
// SÓ atualiza a janela principal se NÃO houver atendimento em andamento
floatingWin.webContents.executeJavaScript("localStorage.getItem('atendimentoAtual')").then(atendimentoAtualId => {
if (!atendimentoAtualId && mainWin && !mainWin.isDestroyed()) {
mainWin.webContents.executeJavaScript(updateStorageScript);
mainWin.webContents.send('load-data', proximos);
}
resolve(proximos);
}).catch(err => {
console.error("Erro ao verificar atendimento atual:", err);
resolve(proximos);
});
} else {
console.error(`Erro na requisição: Status code ${response.statusCode}`, parsedData);
console.error(`Erro API: ${response.statusCode}`);
resolve([]);
}
} catch (error) {
console.error("Erro ao analisar a resposta JSON:", error);
mainWin.webContents.send('api-error', {
message: `Erro ao processar resposta do servidor.`
});
console.error("Erro JSON:", error);
resolve([]);
}
});
});
request.on('error', (error) => {
console.error("Erro na requisição:", error);
console.error("Erro rede:", error);
resolve([]);
});
request.end();
return JSON.parse(await floatingWin.webContents.executeJavaScript("localStorage.getItem('proximos')"));
});
}
// Função para coletar a lista de atendimentos do servidor, vai ser chamada uma vez e a cada 30s
// Atualiza a função de monitoramento para realmente buscar dados a cada 30s (ou o que desejar)
async function getDataAndUpdateFloatingBtn() {
const stored = await floatingWin.webContents.executeJavaScript("localStorage.getItem('proximos')");
const proximos = JSON.parse(stored || '[]');
let count = proximos.length;
//lista a contagem no botão flutuante
floatingWin.webContents.send('update-count', count);
await getFirstData();
}
// Função para verificar se o token existe no localStorage
@ -503,9 +515,12 @@ async function getSelectedOperatorId() {
}
ipcMain.handle('get-pusher-config', async () => {
// Obtenha sua chave e host de forma segura aqui (ambiente, .env, etc.)
const PUSHER_HOST = process.env.PUSHER_HOST || pusherUrl;
return { host: PUSHER_HOST };
// Garante que o host não termine com barra para o Socket.io
let host = pusherUrl;
if (host && host.endsWith('/')) {
host = host.slice(0, -1);
}
return { host: host };
});
ipcMain.on('update_version', async (event, arg) => {
@ -532,8 +547,13 @@ ipcMain.handle('get-count', async () => {
return data.length;
});
let isCallingNext = false;
// Ouvir pedido para mostrar a janela principal
ipcMain.on('chamar-fila', async () => {
// Evita múltiplas chamadas simultâneas
if (isCallingNext) return;
isCallingNext = true;
// Primeiro, verifica se já existe um atendimento em andamento
const atendimentoAtualId = await floatingWin.webContents.executeJavaScript("localStorage.getItem('atendimentoAtual')");
@ -556,21 +576,13 @@ ipcMain.on('chamar-fila', async () => {
}
// Se um atendimento já estiver em andamento, apenas mostra a janela principal.
// A lógica em renderer.js cuidará de exibir a tela de observação.
if (atendimentoAtualId) {
showMainWindow();
return; // Interrompe a execução aqui
}
// Se não houver atendimento em andamento, continua com a lógica original.
const countFila = async () => {
const stored = await floatingWin.webContents.executeJavaScript("localStorage.getItem('proximos')");
const proximos = JSON.parse(stored || '[]');
return proximos.length;
isCallingNext = false;
return;
}
const requestData = async () => {
const colabId = await getSelectedOperatorId();
const token = await getAuthToken();
const tenantId = await getTenantId();
@ -588,25 +600,22 @@ ipcMain.on('chamar-fila', async () => {
request.on('response', (response) => {
let rawData = '';
response.on('data', (chunk) => {
rawData += chunk;
});
response.on('data', (chunk) => { rawData += chunk; });
response.on('end', () => {
isCallingNext = false;
try {
const parsedData = JSON.parse(rawData);
if (response.statusCode === 201 || response.statusCode === 200) {
if (parsedData) {
mainWin.webContents.send('select-atend-id', parsedData);
if (parsedData.status === 'Fila' || parsedData.status === 'Chamado') { showMainWindow(); } else
if (parsedData.status === 'Atendendo') {
if (parsedData.status === 'Fila' || parsedData.status === 'Chamado') {
showMainWindow();
} else if (parsedData.status === 'Atendendo') {
let options2 = {
'title': 'Precisa finalizar antes de chamar o próximo.',
'message': 'Em andamento',
'detail': 'Já possui um atendimento em andamento (Atendendo: ' + parsedData.clientName + '), continue e finalize por favor!',
'type': 'error',
'noLink': true,
'buttons': ['Depois', 'Continuar'],
};
dialog.showMessageBox(floatingWin, options2).then(result => {
@ -637,6 +646,7 @@ ipcMain.on('chamar-fila', async () => {
});
request.on('error', (error) => {
isCallingNext = false;
console.error("Erro na requisição:", error);
mainWin.webContents.send('api-error', {
message: `Erro ao chamar atendimento: ${error.message}`
@ -646,7 +656,11 @@ ipcMain.on('chamar-fila', async () => {
request.end();
};
const countFilaValue = async () => {
const stored = await floatingWin.webContents.executeJavaScript("localStorage.getItem('proximos')");
const proximos = JSON.parse(stored || '[]');
return proximos.length;
}
let options = {
'title': 'Incie o atendimento quando o cliente chegar na sala.',
@ -656,17 +670,20 @@ ipcMain.on('chamar-fila', async () => {
'buttons': ['Não', 'Sim'],
};
if (await countFila()) {
const count = await countFilaValue();
if (count > 0) {
dialog.showMessageBox(floatingWin, options).then(result => {
if (result.response) {
if (result.response === 1) { // 1 é 'Sim'
requestData();
};
} else {
isCallingNext = false;
}
});
} else {
requestData();
// Se a fila estiver vazia, apenas abre a janela principal para visualização
showMainWindow();
isCallingNext = false;
}
});
// Ouve um pedido da janela flutuante para forçar a atualização da contagem
@ -730,6 +747,13 @@ ipcMain.on('atendimento-finalizado', () => {
}
});
// Ouve atualização da fila vinda do renderer (via socket)
ipcMain.on('update-queue', (event, data) => {
// Sempre busca dados frescos da API quando o socket notifica mudança,
// pois o socket pode enviar apenas o objeto da mudança e não a lista completa.
getFirstData();
});
// Ouvir clique no botão "Salvar"
ipcMain.on('save-observation', async (event, { itemId, observation }) => {

View File

@ -18,6 +18,9 @@ contextBridge.exposeInMainWorld('electronAPI', {
atendimentoIniciado: (itemId) => ipcRenderer.send('atendimento-iniciado', itemId),
atendimentoFinalizado: () => ipcRenderer.send('atendimento-finalizado'),
//notifica o main process sobre atualização na fila vinda do socket
updateQueue: (data) => ipcRenderer.send('update-queue', data),
showObservation: (callback) => ipcRenderer.on('show-observation', (_event) => callback() ),
//salva a observação do atendimento
saveObservation: (data) => ipcRenderer.send('save-observation', data),

View File

@ -17,12 +17,15 @@ let selectedItemId = null;
let selectedItemName = '';
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;
}
nextButton.disabled = true;
if (!data) {
return;
}
// Reseta a view para a lista sempre que os dados são carregados
populateList(data[0]);
populateList(data);
});
async function initializeSocket() {
@ -51,9 +54,10 @@ async function initializeSocket() {
// Evento que substitui o bind do Pusher
socket.on('queueUpdate', (data) => {
console.log('Atualização de fila recebida:', data);
localStorage.setItem('proximos', JSON.stringify(data));
populateList(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) => {
@ -182,6 +186,7 @@ nextButton.addEventListener('click', () => {
localStorage.setItem('atendimentoAtualNome', selectedItemName);
// Notifica o main process e muda a view
// IMPORTANTE: iniciaAtendimento deve apenas mudar o status na API, não chamar o próximo.
window.electronAPI.atendimentoIniciado(selectedItemId);
window.electronAPI.iniciaAtendimento(selectedItemId);
showObservationView(); // Muda para a tela de observação