feat: integration with nest-backend and alphanumeric cnpj support
This commit is contained in:
parent
96ac1510ae
commit
624b6a7268
|
|
@ -7,7 +7,7 @@
|
|||
default-src 'self';
|
||||
script-src 'self' 'unsafe-inline';
|
||||
style-src 'self' 'unsafe-inline';
|
||||
connect-src 'self' ws://autoatend.linco.work:6001 ws://localhost:6001 wss://aa.linco.work:443;
|
||||
connect-src 'self' ws://localhost:3000 http://localhost:3000;
|
||||
">
|
||||
<title>Tela de Atendimento</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
|
|
@ -45,7 +45,7 @@
|
|||
<button id="save-button">Salvar</button>
|
||||
</div>
|
||||
|
||||
<script src="res/js/pusher.min.js"></script>
|
||||
<script src="res/js/socket.io.min.js"></script>
|
||||
<script src="renderer.js"></script>
|
||||
|
||||
</body>
|
||||
|
|
|
|||
156
main.js
156
main.js
|
|
@ -14,7 +14,14 @@ let updateWin;
|
|||
|
||||
const dataPath = path.join(__dirname, 'data.json'); // Caminho para o JSON (backup local)
|
||||
const settingsPath = path.join(app.getPath('userData'), 'settings.json'); // Caminho para as configurações
|
||||
const apiUrl = 'https://autoatend.linco.work/api/v1/';
|
||||
|
||||
//! API
|
||||
const apiUrl = 'http://localhost:3000/api/'; // Adaptado para NestJS
|
||||
//! pusher
|
||||
const pusherUrl = 'http://localhost:3000'; // Agora aponta para o Socket.io (NestJS)
|
||||
|
||||
autoUpdater.autoDownload = false;
|
||||
autoUpdater.autoInstallOnAppQuit = true;
|
||||
|
||||
//? Função para ler as configurações
|
||||
function getSettings() {
|
||||
|
|
@ -52,12 +59,6 @@ ipcMain.on('set-setting', (event, key, value) => {
|
|||
});
|
||||
//! final de configurações
|
||||
|
||||
//!pusher
|
||||
const pusherUrl = 'aa.linco.work';
|
||||
|
||||
autoUpdater.autoDownload = false;
|
||||
autoUpdater.autoInstallOnAppQuit = true;
|
||||
|
||||
//impede que o app seja executado mais de uma vez
|
||||
const gotTheLock = app.requestSingleInstanceLock();
|
||||
|
||||
|
|
@ -112,7 +113,8 @@ async function getFirstData() {
|
|||
|
||||
const token = await getAuthToken();
|
||||
const colabId = await floatingWin.webContents.executeJavaScript("localStorage.getItem('idOperator')")
|
||||
const url = apiUrl + 'get-proximos/' + colabId;
|
||||
const tenantId = await floatingWin.webContents.executeJavaScript("localStorage.getItem('tenantId')")
|
||||
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; }
|
||||
|
|
@ -123,7 +125,8 @@ async function getFirstData() {
|
|||
url: url,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': 'Bearer ' + token
|
||||
'Authorization': 'Bearer ' + token,
|
||||
'x-tenant-id': tenantId
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -134,7 +137,7 @@ async function getFirstData() {
|
|||
response.on('end', () => {
|
||||
try {
|
||||
const parsedData = JSON.parse(rawData);
|
||||
let proximos = parsedData;
|
||||
let proximos = Array.isArray(parsedData) ? parsedData : [];
|
||||
if (response.statusCode === 200) {
|
||||
floatingWin.webContents.executeJavaScript("localStorage.setItem('proximos','" + JSON.stringify(proximos) + "')");
|
||||
let count = proximos.length;
|
||||
|
|
@ -162,7 +165,8 @@ async function getFirstData() {
|
|||
// Função para coletar a lista de atendimentos do servidor, vai ser chamada uma vez e a cada 30s
|
||||
async function getDataAndUpdateFloatingBtn() {
|
||||
|
||||
const proximos = JSON.parse(await floatingWin.webContents.executeJavaScript("localStorage.getItem('proximos')")) ?? [];
|
||||
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
|
||||
|
|
@ -446,11 +450,11 @@ async function getSelectedOperator() {
|
|||
.then(operator => resolve(operator))
|
||||
.catch(() => resolve(null));
|
||||
} else if (mainWin && !mainWin.isDestroyed()) {
|
||||
mainWin.webContents.executeJavaScript('localStorage.getItem("selectedOperator");')
|
||||
mainWin.webContents.executeJavaScript('localStorage.getItem("authToken");')
|
||||
.then(operator => resolve(operator))
|
||||
.catch(() => resolve(null));
|
||||
} else if (floatingWin && !floatingWin.isDestroyed()) {
|
||||
floatingWin.webContents.executeJavaScript('localStorage.getItem("selectedOperator");')
|
||||
floatingWin.webContents.executeJavaScript('localStorage.getItem("authToken");')
|
||||
.then(operator => resolve(operator))
|
||||
.catch(() => resolve(null));
|
||||
} else {
|
||||
|
|
@ -477,9 +481,8 @@ async function getSelectedOperatorId() {
|
|||
|
||||
ipcMain.handle('get-pusher-config', async () => {
|
||||
// Obtenha sua chave e host de forma segura aqui (ambiente, .env, etc.)
|
||||
const PUSHER_APP_KEY = process.env.PUSHER_APP_KEY || '1feb970af7708cb';
|
||||
const PUSHER_HOST = process.env.PUSHER_HOST || pusherUrl;
|
||||
return { appKey: PUSHER_APP_KEY, host: PUSHER_HOST };
|
||||
return { host: PUSHER_HOST };
|
||||
});
|
||||
|
||||
ipcMain.on('update_version', async (event, arg) => {
|
||||
|
|
@ -538,25 +541,25 @@ ipcMain.on('chamar-fila', async () => {
|
|||
|
||||
// Se não houver atendimento em andamento, continua com a lógica original.
|
||||
const countFila = async () => {
|
||||
const proximos = JSON.parse(await floatingWin.webContents.executeJavaScript("localStorage.getItem('proximos')")) ?? [];
|
||||
const stored = await floatingWin.webContents.executeJavaScript("localStorage.getItem('proximos')");
|
||||
const proximos = JSON.parse(stored || '[]');
|
||||
return proximos.length;
|
||||
}
|
||||
|
||||
const requestData = async () => {
|
||||
|
||||
|
||||
|
||||
|
||||
const colabId = await getSelectedOperatorId();
|
||||
const token = await getAuthToken('token');
|
||||
const url = apiUrl + 'chama-fila-app-colab/' + colabId; // URL de exemplo para enviar a solicitação
|
||||
const token = await getAuthToken();
|
||||
const tenantId = await floatingWin.webContents.executeJavaScript("localStorage.getItem('tenantId')")
|
||||
const url = apiUrl + 'attendance/call-next/' + colabId;
|
||||
|
||||
const request = net.request({
|
||||
method: 'GET',
|
||||
method: 'POST',
|
||||
url: url,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': 'Bearer ' + token
|
||||
'Authorization': 'Bearer ' + token,
|
||||
'x-tenant-id': tenantId
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -570,14 +573,15 @@ ipcMain.on('chamar-fila', async () => {
|
|||
response.on('end', () => {
|
||||
try {
|
||||
const parsedData = JSON.parse(rawData);
|
||||
if (response.statusCode === 200) {
|
||||
mainWin.webContents.send('select-atend-id', parsedData.data);
|
||||
if (parsedData.data && (parsedData.data.Status === 'Fila' || parsedData.data.Status === 'Chamado')) { showMainWindow(); } else
|
||||
if (parsedData.data && parsedData.data.Status === 'Atendendo') {
|
||||
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') {
|
||||
let options2 = {
|
||||
'title': 'Precisa finalizar antes de chamar o próximo.',
|
||||
'message': 'Em andamento',
|
||||
'detail': 'Já possui um atendimento em andamento (Atendendo: ' + parsedData.data.clientName + '), continue e finalize por favor!',
|
||||
'detail': 'Já possui um atendimento em andamento (Atendendo: ' + parsedData.clientName + '), continue e finalize por favor!',
|
||||
'type': 'error',
|
||||
'noLink': true,
|
||||
'buttons': ['Depois', 'Continuar'],
|
||||
|
|
@ -591,10 +595,11 @@ ipcMain.on('chamar-fila', async () => {
|
|||
};
|
||||
});
|
||||
}
|
||||
// console.log(parsedData);
|
||||
} else {
|
||||
mainWin.webContents.send('select-atend-id', null);
|
||||
}
|
||||
} else {
|
||||
console.error(`Erro na requisição: Status code ${response.statusCode}`, parsedData);
|
||||
// Lidar com o erro adequadamente, talvez enviando uma mensagem para a janela principal
|
||||
mainWin.webContents.send('api-error', {
|
||||
message: `Erro ao chamar atendimento: ${parsedData.message || 'Erro desconhecido'}`
|
||||
});
|
||||
|
|
@ -644,7 +649,8 @@ ipcMain.on('chamar-fila', async () => {
|
|||
// Ouve um pedido da janela flutuante para forçar a atualização da contagem
|
||||
ipcMain.on('refresh-count', async () => {
|
||||
if (floatingWin) {
|
||||
const proximos = JSON.parse(await floatingWin.webContents.executeJavaScript("localStorage.getItem('proximos')")) ?? [];
|
||||
const stored = await floatingWin.webContents.executeJavaScript("localStorage.getItem('proximos')");
|
||||
const proximos = JSON.parse(stored || '[]');
|
||||
floatingWin.webContents.send('update-count', proximos.length);
|
||||
}
|
||||
});
|
||||
|
|
@ -658,44 +664,33 @@ ipcMain.on('select-atend-id', (itemId) => {
|
|||
ipcMain.on('iniciar-atendimento', async (event, itemId) => {
|
||||
|
||||
const token = await getAuthToken();
|
||||
const colabId = await floatingWin.webContents.executeJavaScript("localStorage.getItem('idOperator')")
|
||||
//TODO inicia o atendimento o id do atendimento deve ser requisitado do backend
|
||||
|
||||
const url = apiUrl + 'iniciar-atendimento/' + itemId; // URL para enviar a solicitação
|
||||
const tenantId = await floatingWin.webContents.executeJavaScript("localStorage.getItem('tenantId')")
|
||||
const url = apiUrl + 'attendance/' + itemId + '/start';
|
||||
|
||||
// envio de uma solicitação POST com o ID do item
|
||||
const request = net.request({
|
||||
method: 'GET',
|
||||
method: 'PATCH',
|
||||
url: url,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': 'Bearer ' + token
|
||||
'Authorization': 'Bearer ' + token,
|
||||
'x-tenant-id': tenantId
|
||||
}
|
||||
});
|
||||
|
||||
request.on('response', (response) => {
|
||||
// console.log(`STATUS: ${response.statusCode}`);
|
||||
// console.log(`HEADERS: ${JSON.stringify(response.headers)}`);
|
||||
response.on('data', (chunk) => {
|
||||
console.log(`BODY: ${chunk}`);
|
||||
});
|
||||
response.on('end', () => {
|
||||
console.log('Solicitação concluída.');
|
||||
// Avisa a janela principal que a solicitação foi feita (opcional)
|
||||
// mainWin.webContents.send('request-done', itemId);
|
||||
});
|
||||
});
|
||||
request.on('error', (error) => {
|
||||
console.error(`Erro na solicitação: ${error}`);
|
||||
// Poderia notificar a UI sobre o erro
|
||||
});
|
||||
|
||||
// Envia o ID como corpo da requisição (exemplo)
|
||||
request.write(JSON.stringify({ id: itemId }));
|
||||
request.end();
|
||||
|
||||
// Não precisamos esperar a resposta para mudar a UI na janela principal
|
||||
// A janela principal já mudou a UI ao enviar o evento 'next-step'
|
||||
});
|
||||
|
||||
// Ouve quando um atendimento é iniciado e notifica a janela flutuante
|
||||
|
|
@ -715,19 +710,14 @@ ipcMain.on('atendimento-finalizado', () => {
|
|||
// Ouvir clique no botão "Salvar"
|
||||
ipcMain.on('save-observation', async (event, { itemId, observation }) => {
|
||||
|
||||
//TODO salva a observação e finaliza o atendimento
|
||||
|
||||
console.log(`Salvando observação para item ${itemId}: ${observation}`);
|
||||
|
||||
const token = await getAuthToken();
|
||||
const colabId = await floatingWin.webContents.executeJavaScript("localStorage.getItem('idOperator')")
|
||||
//TODO inicia o atendimento o id do atendimento deve ser requisitado do backend
|
||||
|
||||
const url = apiUrl + 'finalizar-atendimento/' + itemId; // URL de exemplo para enviar a solicitação
|
||||
const tenantId = await floatingWin.webContents.executeJavaScript("localStorage.getItem('tenantId')")
|
||||
const url = apiUrl + 'attendance/' + itemId + '/finish';
|
||||
|
||||
const fmData = JSON.stringify({
|
||||
"colabId": colabId,
|
||||
"obsAtendimento": observation
|
||||
"observation": observation
|
||||
});
|
||||
|
||||
|
||||
|
|
@ -737,7 +727,8 @@ ipcMain.on('save-observation', async (event, { itemId, observation }) => {
|
|||
url: url,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': 'Bearer ' + token
|
||||
'Authorization': 'Bearer ' + token,
|
||||
'x-tenant-id': tenantId
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -747,13 +738,10 @@ ipcMain.on('save-observation', async (event, { itemId, observation }) => {
|
|||
});
|
||||
response.on('end', () => {
|
||||
console.log('Solicitação concluída.');
|
||||
// Avisa a janela principal que a solicitação foi feita (opcional)
|
||||
// mainWin.webContents.send('request-done', itemId);
|
||||
});
|
||||
});
|
||||
request.on('error', (error) => {
|
||||
console.error(`Erro na solicitação: ${error}`);
|
||||
// Poderia notificar a UI sobre o erro
|
||||
});
|
||||
|
||||
// Envia o ID como corpo da requisição (exemplo)
|
||||
|
|
@ -763,28 +751,17 @@ ipcMain.on('save-observation', async (event, { itemId, observation }) => {
|
|||
|
||||
// Opcional: Fechar ou resetar a janela principal após salvar
|
||||
if (mainWin) {
|
||||
mainWin.hide(); // Ou mainWin.webContents.send('reset-view');
|
||||
mainWin.hide();
|
||||
}
|
||||
});
|
||||
|
||||
// Permite que a janela flutuante seja arrastada
|
||||
// REMOVA ou comente este listener inteiro:
|
||||
/*
|
||||
ipcMain.on('drag-float-window', (event, { offsetX, offsetY }) => {
|
||||
if (floatingWin) {
|
||||
const { x, y } = screen.getCursorScreenPoint();
|
||||
floatingWin.setPosition(x - offsetX, y - offsetY);
|
||||
}
|
||||
});
|
||||
*/
|
||||
|
||||
|
||||
ipcMain.on('logout', () => {
|
||||
mainWin.webContents.executeJavaScript(`
|
||||
localStorage.removeItem("idOperator");
|
||||
localStorage.removeItem("selectedOperator");
|
||||
localStorage.removeItem("salaOperator");
|
||||
localStorage.removeItem("servicosOperator");
|
||||
localStorage.removeItem("tenantId");
|
||||
`).then(() => {
|
||||
// Fecha a janela main e abre a janela de operador e inicia o aplicativo
|
||||
mainWin.hide();
|
||||
|
|
@ -797,8 +774,7 @@ ipcMain.on('logout', () => {
|
|||
// Handler para login
|
||||
ipcMain.on('login-attempt', async (event, credentials) => {
|
||||
try {
|
||||
// Substitua pela URL real da sua API de autenticação
|
||||
const route = apiUrl + 'login';
|
||||
const route = apiUrl + 'auth/login';
|
||||
|
||||
const request = net.request({
|
||||
method: 'POST',
|
||||
|
|
@ -813,19 +789,17 @@ ipcMain.on('login-attempt', async (event, credentials) => {
|
|||
request.on('response', (response) => {
|
||||
response.on('data', (chunk) => {
|
||||
responseData += chunk.toString();
|
||||
console.log("Resposta da API:", responseData); // Adiciona este log para ver a resposta crua
|
||||
});
|
||||
|
||||
response.on('end', () => {
|
||||
try {
|
||||
const data = JSON.parse(responseData);
|
||||
|
||||
|
||||
if (data.status === 'Authorized' && data.api_key) {
|
||||
if (data.access_token) {
|
||||
// Login bem-sucedido
|
||||
loginWin.webContents.executeJavaScript(`
|
||||
localStorage.setItem("authToken", "${data.api_key}");
|
||||
localStorage.setItem("channel", "${data.channel}");
|
||||
localStorage.setItem("authToken", "${data.access_token}");
|
||||
localStorage.setItem("tenantId", "${data.user.tenantId}");
|
||||
`).then(() => {
|
||||
// Fecha a janela de login e abre a de seleção de operador
|
||||
event.reply('login-response', { success: true });
|
||||
|
|
@ -841,7 +815,6 @@ ipcMain.on('login-attempt', async (event, credentials) => {
|
|||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.log("Resposta da API:", error);
|
||||
event.reply('login-response', {
|
||||
success: false,
|
||||
message: 'Erro ao processar resposta do servidor'
|
||||
|
|
@ -858,7 +831,7 @@ ipcMain.on('login-attempt', async (event, credentials) => {
|
|||
});
|
||||
|
||||
// Envia as credenciais
|
||||
request.write(JSON.stringify(credentials));
|
||||
request.write(JSON.stringify({ login: credentials.login, password: credentials.password }));
|
||||
request.end();
|
||||
} catch (error) {
|
||||
event.reply('login-response', {
|
||||
|
|
@ -906,10 +879,7 @@ ipcMain.handle('get-operators', async () => {
|
|||
};
|
||||
}
|
||||
|
||||
// Aqui você pode fazer uma chamada à API para obter os operadores
|
||||
// Por enquanto, vamos retornar alguns operadores de exemplo
|
||||
// Substitua pela URL real da sua API de autenticação
|
||||
const route = apiUrl + 'colabs/list';
|
||||
const route = apiUrl + 'collaborators';
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const request = net.request({
|
||||
|
|
@ -926,19 +896,18 @@ ipcMain.handle('get-operators', async () => {
|
|||
request.on('response', (response) => {
|
||||
response.on('data', (chunk) => {
|
||||
responseData += chunk.toString();
|
||||
console.log("Resposta da API:", responseData); // Adiciona este log para ver a resposta crua
|
||||
});
|
||||
|
||||
response.on('end', () => {
|
||||
try {
|
||||
const data = JSON.parse(responseData);
|
||||
|
||||
if (data.colabs) {
|
||||
const operators = data.colabs.map(colab => ({
|
||||
id: colab.id,
|
||||
name: colab.nome.toUpperCase(),
|
||||
sala: colab.sala,
|
||||
servicos: colab.servicos
|
||||
if (Array.isArray(data)) {
|
||||
const operators = data.map(colab => ({
|
||||
id: colab._id,
|
||||
name: colab.name.toUpperCase(),
|
||||
sala: colab.roomId?.name || 'Sala',
|
||||
servicos: colab.serviceIds?.map(s => s.name).join(',') || ''
|
||||
}));
|
||||
|
||||
resolve({
|
||||
|
|
@ -948,12 +917,11 @@ ipcMain.handle('get-operators', async () => {
|
|||
} else {
|
||||
reject({
|
||||
success: false,
|
||||
message: data.message || 'Erro ao obter a lista de colaboradores',
|
||||
message: 'Erro ao obter a lista de colaboradores',
|
||||
operators: []
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.log("Erro ao processar resposta da API:", error);
|
||||
reject({
|
||||
success: false,
|
||||
message: 'Erro ao processar resposta do servidor',
|
||||
|
|
|
|||
|
|
@ -1,18 +1,19 @@
|
|||
{
|
||||
"name": "autoatendcolab",
|
||||
"version": "1.0.7",
|
||||
"version": "1.1.5",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "autoatendcolab",
|
||||
"version": "1.0.7",
|
||||
"version": "1.1.5",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@electron/remote": "^2.1.2",
|
||||
"electron-single-instance": "^0.0.2",
|
||||
"electron-updater": "^6.6.2",
|
||||
"jquery": "^3.7.1"
|
||||
"jquery": "^3.7.1",
|
||||
"socket.io-client": "^4.8.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"electron": "^35.2.1",
|
||||
|
|
@ -952,6 +953,12 @@
|
|||
"url": "https://github.com/sindresorhus/is?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/@socket.io/component-emitter": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz",
|
||||
"integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@szmarczak/http-timer": {
|
||||
"version": "4.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz",
|
||||
|
|
@ -2041,9 +2048,10 @@
|
|||
}
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
|
||||
"integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
|
||||
"version": "4.4.3",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
|
||||
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ms": "^2.1.3"
|
||||
},
|
||||
|
|
@ -2743,6 +2751,28 @@
|
|||
"once": "^1.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/engine.io-client": {
|
||||
"version": "6.6.4",
|
||||
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.4.tgz",
|
||||
"integrity": "sha512-+kjUJnZGwzewFDw951CDWcwj35vMNf2fcj7xQWOctq1F2i1jkDdVvdFG9kM/BEChymCH36KgjnW0NsL58JYRxw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@socket.io/component-emitter": "~3.1.0",
|
||||
"debug": "~4.4.1",
|
||||
"engine.io-parser": "~5.2.1",
|
||||
"ws": "~8.18.3",
|
||||
"xmlhttprequest-ssl": "~2.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/engine.io-parser": {
|
||||
"version": "5.2.3",
|
||||
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz",
|
||||
"integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/env-paths": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
|
||||
|
|
@ -5029,6 +5059,34 @@
|
|||
"npm": ">= 3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/socket.io-client": {
|
||||
"version": "4.8.3",
|
||||
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.8.3.tgz",
|
||||
"integrity": "sha512-uP0bpjWrjQmUt5DTHq9RuoCBdFJF10cdX9X+a368j/Ft0wmaVgxlrjvK3kjvgCODOMMOz9lcaRzxmso0bTWZ/g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@socket.io/component-emitter": "~3.1.0",
|
||||
"debug": "~4.4.1",
|
||||
"engine.io-client": "~6.6.1",
|
||||
"socket.io-parser": "~4.2.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/socket.io-parser": {
|
||||
"version": "4.2.6",
|
||||
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.6.tgz",
|
||||
"integrity": "sha512-asJqbVBDsBCJx0pTqw3WfesSY0iRX+2xzWEWzrpcH7L6fLzrhyF8WPI8UaeM4YCuDfpwA/cgsdugMsmtz8EJeg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@socket.io/component-emitter": "~3.1.0",
|
||||
"debug": "~4.4.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/socks": {
|
||||
"version": "2.8.4",
|
||||
"resolved": "https://registry.npmjs.org/socks/-/socks-2.8.4.tgz",
|
||||
|
|
@ -5734,6 +5792,27 @@
|
|||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
|
||||
},
|
||||
"node_modules/ws": {
|
||||
"version": "8.18.3",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz",
|
||||
"integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"bufferutil": "^4.0.1",
|
||||
"utf-8-validate": ">=5.0.2"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"bufferutil": {
|
||||
"optional": true
|
||||
},
|
||||
"utf-8-validate": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/xmlbuilder": {
|
||||
"version": "15.1.1",
|
||||
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz",
|
||||
|
|
@ -5744,6 +5823,14 @@
|
|||
"node": ">=8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/xmlhttprequest-ssl": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.2.tgz",
|
||||
"integrity": "sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==",
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/y18n": {
|
||||
"version": "5.0.8",
|
||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
|
||||
|
|
|
|||
|
|
@ -40,7 +40,8 @@
|
|||
"@electron/remote": "^2.1.2",
|
||||
"electron-single-instance": "^0.0.2",
|
||||
"electron-updater": "^6.6.2",
|
||||
"jquery": "^3.7.1"
|
||||
"jquery": "^3.7.1",
|
||||
"socket.io-client": "^4.8.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"electron": "^35.2.1",
|
||||
|
|
|
|||
87
renderer.js
87
renderer.js
|
|
@ -25,61 +25,47 @@ window.electronAPI.onLoadData((data) => {
|
|||
populateList(data[0]);
|
||||
});
|
||||
|
||||
async function initializePusher() {
|
||||
async function initializeSocket() {
|
||||
if (typeof window.electronAPI === 'undefined' || !window.electronAPI.getPusherConfig) {
|
||||
console.error('electronAPI not available or getPusherConfig method missing.');
|
||||
return;
|
||||
}
|
||||
|
||||
const pusherConfig = await window.electronAPI.getPusherConfig();
|
||||
const PUSHER_APP_KEY = pusherConfig.appKey;
|
||||
let host = pusherConfig.host;
|
||||
const config = await window.electronAPI.getPusherConfig();
|
||||
let host = config.host;
|
||||
|
||||
const channelLocal = localStorage.getItem('channel');
|
||||
const colabId = localStorage.getItem('idOperator');
|
||||
const tenantId = localStorage.getItem('tenantId');
|
||||
const token = localStorage.getItem('authToken');
|
||||
|
||||
//! checa se ja tem o colabId
|
||||
if (channelLocal && colabId && PUSHER_APP_KEY) {
|
||||
Pusher.logToConsole = true;
|
||||
|
||||
var pusher = new Pusher(PUSHER_APP_KEY, {
|
||||
wsHost: host,
|
||||
wsPort: 80,
|
||||
wssPort: 443,
|
||||
forceTLS: true,
|
||||
enableStats: false,
|
||||
enabledTransports: ['wss', 'ws'],
|
||||
cluster: 'mt1'
|
||||
//! 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 }
|
||||
});
|
||||
|
||||
let channel;
|
||||
if (pusher.connection.state === 'connected') {
|
||||
pusher.unsubscribe('chat.' + channelLocal + '_' + colabId);
|
||||
}
|
||||
socket.on('connect', () => {
|
||||
console.log('Socket.io conectado ao host: ', host);
|
||||
});
|
||||
|
||||
channel = pusher.subscribe('chat.' + channelLocal + '_' + colabId);
|
||||
|
||||
channel.bind('message-sent', function (r) {
|
||||
let data = r.data.fila.original;
|
||||
let count = data.length;
|
||||
console.log(data);
|
||||
// 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(r.data.currentData.original);
|
||||
|
||||
populateList(data);
|
||||
});
|
||||
|
||||
pusher.connection.bind('error', function (err) {
|
||||
console.error('Pusher connection error: ', err);
|
||||
socket.on('error', (err) => {
|
||||
console.error('Socket.io connection error: ', err);
|
||||
});
|
||||
|
||||
console.log('Host de conexão: ', host);
|
||||
} else {
|
||||
console.warn('User not authenticated or Pusher APP_KEY not available. Private channel not subscribed.');
|
||||
console.warn('User not authenticated or tenantId not available. WebSocket not connected.');
|
||||
}
|
||||
}
|
||||
|
||||
initializePusher();
|
||||
initializeSocket();
|
||||
|
||||
//chama o proximo da fila ao abrir a janela de atendimentos
|
||||
window.electronAPI.selectAtendID((data) => {
|
||||
|
|
@ -93,12 +79,12 @@ window.electronAPI.selectAtendID((data) => {
|
|||
showListView();
|
||||
|
||||
// Garante que o item selecionado (ID e Nome) seja o que veio da chamada, sobrescrevendo o da lista.
|
||||
selectedItemId = data.id ?? null;
|
||||
selectedItemId = data._id ?? null;
|
||||
selectedItemName = data.clientName ?? '';
|
||||
|
||||
//data.senhaGen
|
||||
queueNumber.innerHTML = data ? `NA VEZ: <u>${data.clientName.toUpperCase()}</u> - ${data.descricaoServico.toUpperCase()}` : 'Ninguem aguardando atendimento';
|
||||
selectedItemNameSpan.innerHTML = data ? `<u> ${data.clientName.toUpperCase()} </u> <i style="float:right;">[ ${data.senhaGen} ]</i>` : 'Ninguem aguardando atendimento';
|
||||
queueNumber.innerHTML = data ? `NA VEZ: <u>${data.clientName.toUpperCase()}</u>` : 'Ninguem aguardando atendimento';
|
||||
selectedItemNameSpan.innerHTML = data ? `<u> ${data.clientName.toUpperCase()} </u> <i style="float:right;">[ ${data.ticketNumber} ]</i>` : 'Ninguem aguardando atendimento';
|
||||
});
|
||||
|
||||
window.electronAPI.showObservation(() => {
|
||||
|
|
@ -107,7 +93,7 @@ window.electronAPI.showObservation(() => {
|
|||
});
|
||||
|
||||
// Função para popular a lista de itens
|
||||
function populateList(currentData) {
|
||||
function populateList(proximos) {
|
||||
const atendimentoEmAndamentoId = localStorage.getItem('atendimentoAtual');
|
||||
const atendimentoEmAndamentoNome = localStorage.getItem('atendimentoAtualNome');
|
||||
|
||||
|
|
@ -118,25 +104,27 @@ function populateList(currentData) {
|
|||
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 || '[]');
|
||||
}
|
||||
|
||||
// Adiciona os outros itens apenas para visualização (opcional)
|
||||
const proximos = JSON.parse(datastorage);
|
||||
itemList.innerHTML = '';
|
||||
|
||||
setTimeout(() => {
|
||||
nextButton.disabled = !currentData;
|
||||
}, 5000);
|
||||
nextButton.disabled = !proximos || proximos.length === 0;
|
||||
}, 1000);
|
||||
|
||||
// Seleciona o primeiro item por padrão (ou o próximo disponível)
|
||||
// Aqui, vamos apenas pegar o primeiro da lista atual
|
||||
const itemToProcess = proximos[0]; // Pega o primeiro item
|
||||
if (itemToProcess) {
|
||||
selectedItemId = itemToProcess.id;
|
||||
selectedItemId = itemToProcess._id;
|
||||
selectedItemName = itemToProcess.clientName;
|
||||
const li = document.createElement('li');
|
||||
li.innerHTML = /*${itemToProcess.senhaGen}: */ `<u>${itemToProcess.clientName.toUpperCase()}</u> - ${itemToProcess.attendanceType.toUpperCase()} - ${itemToProcess.descricaoServico.toUpperCase()}`;
|
||||
li.dataset.id = itemToProcess.id; // Armazena o ID no elemento
|
||||
li.innerHTML = /*${itemToProcess.ticketNumber}: */ `<u>${itemToProcess.clientName.toUpperCase()}</u> - ${itemToProcess.ticketNumber}`;
|
||||
li.dataset.id = itemToProcess._id; // Armazena o ID no elemento
|
||||
li.classList.add('selected'); // Marca como selecionado visualmente (precisa de CSS)
|
||||
itemList.appendChild(li);
|
||||
} else {
|
||||
|
|
@ -149,8 +137,7 @@ function populateList(currentData) {
|
|||
// Adiciona os outros itens apenas para visualização (opcional)
|
||||
proximos.slice(1).forEach(item => {
|
||||
const li = document.createElement('li');
|
||||
//${item.senhaGen}:
|
||||
li.textContent = `${item.clientName.toUpperCase()} - ${item.attendanceType.toUpperCase()} - ${item.descricaoServico.toUpperCase()}`;
|
||||
li.textContent = `${item.clientName.toUpperCase()} - ${item.ticketNumber}`;
|
||||
itemList.appendChild(li);
|
||||
});
|
||||
}
|
||||
|
|
@ -223,5 +210,3 @@ saveButton.addEventListener('click', () => {
|
|||
window.location.reload();
|
||||
}
|
||||
});
|
||||
|
||||
// Inicialmente, mostra a view da lista (estará vazia até receber dados)
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue