// Sistema PELL - Controle de Produção (Modo Somente Leitura)
/* const API_BASE = 'http://localhost:3000/api'; */
// O host da API será o mesmo do endereço que você acessa no navegador
const API_BASE = `${window.location.protocol}//${window.location.hostname}:3000/api`;
// Função utilitária para fazer requisições com autenticação
async function apiRequest(url, options = {}) {
const token = localStorage.getItem('authToken');
const defaultOptions = {
headers: {
'Content-Type': 'application/json',
...(token && { 'Authorization': `Bearer ${token}` })
}
};
const finalOptions = {
...defaultOptions,
...options,
headers: {
...defaultOptions.headers,
...options.headers
}
};
console.log('🚀 API Request:', url, 'Token:', token ? 'EXISTS' : 'MISSING');
const response = await fetch(url, finalOptions);
if (response.status === 401) {
console.log('❌ 401 Unauthorized - redirecting to login');
window.location.href = '/login.html';
throw new Error('Não autorizado');
}
return response;
}
// Estado da aplicação
let paginaAtual = '';
// Função para carregar páginas
async function carregarPagina(pagina) {
const conteudo = document.getElementById('conteudo-principal');
// Atualizar navegação ativa
document.querySelectorAll('.nav-link').forEach(link => {
link.classList.remove('active');
});
event?.target.classList.add('active');
paginaAtual = pagina;
try {
switch (pagina) {
case 'dashboard':
await carregarDashboard(conteudo);
break;
case 'ordens':
await carregarOrdens(conteudo);
break;
case 'acompanhamento':
await carregarAcompanhamento(conteudo);
break;
case 'relatorios':
await carregarRelatorios(conteudo);
break;
case 'whatsapp':
await carregarWhatsApp(conteudo);
break;
case 'clientes':
await carregarClientes(conteudo);
break;
case 'materiais':
await carregarMateriais(conteudo);
break;
default:
conteudo.innerHTML = '
Página não encontrada
';
}
} catch (error) {
console.error('Erro ao carregar página:', error);
conteudo.innerHTML = `Erro ao carregar ${pagina}: ${error.message}
`;
}
}
// Dashboard
async function carregarDashboard(container) {
container.innerHTML = `
`;
try {
const response = await apiRequest(`${API_BASE}/dashboard`);
const data = await response.json();
if (data.status === 'success') {
exibirEstatisticasDashboard(data.data.estatisticas);
exibirGraficoEmpresas(data.data.ordens_por_empresa);
exibirUltimasOrdens(data.data.ultimas_ordens);
} else {
throw new Error(data.message);
}
} catch (error) {
document.getElementById('dashboard-stats').innerHTML =
`Erro ao carregar dashboard: ${error.message}
`;
}
}
// Exibir estatísticas do dashboard
function exibirEstatisticasDashboard(stats) {
const statsContainer = document.getElementById('dashboard-stats');
statsContainer.innerHTML = `
${stats.total_ordens}
Total de Ordens
${stats.ordens_iniciadas}
Iniciadas
${stats.em_testes}
Em Testes
${stats.expedidas}
Expedidas
`;
}
// Gráfico de ordens por empresa
function exibirGraficoEmpresas(dados) {
const ctx = document.getElementById('graficoEmpresas').getContext('2d');
new Chart(ctx, {
type: 'doughnut',
data: {
labels: dados.map(item => item.Empresa || 'Sem empresa'),
datasets: [{
data: dados.map(item => item.total),
backgroundColor: [
'#FF6384', '#36A2EB', '#FFCE56', '#4BC0C0',
'#9966FF', '#FF9F40', '#FF6384', '#C9CBCF',
'#4BC0C0', '#FF6384'
]
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
position: 'bottom'
}
}
}
});
}
// Últimas ordens
function exibirUltimasOrdens(ordens) {
const container = document.getElementById('ultimas-ordens');
if (ordens.length === 0) {
container.innerHTML = 'Nenhuma ordem encontrada
';
return;
}
container.innerHTML = ordens.map(ordem => `
OF #${ordem.idOF}
${ordem.Empresa || 'Sem empresa'} |
${ordem.Matricula || 'Sem máquina'}
${formatarData(ordem.DataPedido)}
Prazo: ${formatarData(ordem.PrazoEntrega)}
`).join('');
}
// Ordens de Fabricação
async function carregarOrdens(container) {
container.innerHTML = `
`;
await buscarOrdens();
}
async function buscarOrdens() {
const tabelaContainer = document.getElementById('tabela-ordens');
try {
const empresa = document.getElementById('filtroEmpresa')?.value || '';
const matricula = document.getElementById('filtroMatricula')?.value || '';
const params = new URLSearchParams();
if (empresa) params.append('empresa', empresa);
if (matricula) params.append('matricula', matricula);
const response = await apiRequest(`${API_BASE}/registros?${params}`);
const data = await response.json();
if (data.status === 'success') {
exibirTabelaOrdens(data.data, tabelaContainer);
} else {
throw new Error(data.message);
}
} catch (error) {
tabelaContainer.innerHTML = `Erro ao buscar ordens: ${error.message}
`;
}
}
function exibirTabelaOrdens(ordens, container) {
if (ordens.length === 0) {
container.innerHTML = 'Nenhuma ordem encontrada com os filtros aplicados
';
return;
}
container.innerHTML = `
Comessa
Cliente
Código Máquina
Nome Comercial
Data do Pedido
Prazo de Entrega
Progresso
Ações
${ordens.map(ordem => `
${ordem.idOF}
${ordem.Empresa || '-'}
${ordem.Matricula || '-'}
${ordem.NomeComercial || '-'}
${formatarData(ordem.DataPedido)}
${formatarData(ordem.PrazoEntrega)}
${gerarWorkflowMini(ordem)}
Ver
`).join('')}
Total: ${ordens.length} ordem(ns) encontrada(s)
`;
}
// Workflow mini para a tabela
function gerarWorkflowMini(ordem) {
const etapas = [
ordem.OrdemFabricacao,
ordem.AprovacaoLayout,
ordem.LiberacaoListasMecanica,
ordem.LiberacaoListasEletrica,
ordem.Separacao,
ordem.PreMontagem,
ordem.PreMontagemEletrica,
ordem.PreMontagemMecanica,
ordem.PreMontagemPainel,
ordem.EletricaMontagem,
ordem.Testes,
ordem.FAT,
ordem.PreparacaoExpedicao
];
let html = '';
etapas.forEach((etapa, index) => {
let classe = 'pendente';
if (etapa === 1) {
classe = 'concluida';
} else if (index > 0 && etapas[index - 1] === 1 && etapa !== 1) {
classe = 'em-andamento';
}
html += `
`;
});
return html;
}
// Funções auxiliares para ordens
function obterStatusOrdem(ordem) {
if (ordem.Expedicao === 1) return 'Expedida ';
if (ordem.Testes === 1) return 'Em Testes ';
if (ordem.OrdemFabricacao === 1) return 'Iniciada ';
return 'Pendente ';
}
function isPrazoVencido(prazoEntrega) {
if (!prazoEntrega) return false;
const hoje = new Date();
const prazo = new Date(prazoEntrega);
return prazo < hoje;
}
function limparFiltrosOrdens() {
document.getElementById('filtroEmpresa').value = '';
document.getElementById('filtroMatricula').value = '';
buscarOrdens();
}
async function verDetalhesOrdem(idOF) {
const modal = new bootstrap.Modal(document.getElementById('modalDetalhes'));
const modalTitle = document.querySelector('#modalDetalhes .modal-title');
const modalBody = document.getElementById('modal-body-content');
modalTitle.textContent = 'Detalhes da Ordem de Fabricação';
modalBody.innerHTML = `
`;
modal.show();
try {
const response = await apiRequest(`${API_BASE}/registros?idof=${idOF}`);
const data = await response.json();
if (data.status === 'success' && data.data.length > 0) {
const ordem = data.data[0];
modalBody.innerHTML = `
Informações Gerais
Comessa: ${ordem.idOF}
Matrícula: ${ordem.Matricula || '-'}
Cliente: ${ordem.Empresa || '-'}
Nome Comercial: ${ordem.NomeComercial || '-'}
Data do Pedido: ${formatarData(ordem.DataPedido)}
Prazo de Entrega: ${formatarData(ordem.PrazoEntrega)}
Responsáveis
${ordem.ResponsavelOrdemFabricacao ? `
OF: ${ordem.ResponsavelOrdemFabricacao}
` : ''}
${ordem.ResponsavelAprovacaoLayout ? `
Layout: ${ordem.ResponsavelAprovacaoLayout}
` : ''}
${ordem.ResponsavelLiberacaoListasMecanica ? `
Lista Mecânica: ${ordem.ResponsavelLiberacaoListasMecanica}
` : ''}
${ordem.ResponsavelLiberacaoListasEletrica ? `
Lista Elétrica: ${ordem.ResponsavelLiberacaoListasEletrica}
` : ''}
${ordem.ResponsavelSeparacao ? `
Separação: ${ordem.ResponsavelSeparacao}
` : ''}
${ordem.ResponsavelPreMontagem ? `
Pré-Montagem: ${ordem.ResponsavelPreMontagem}
` : ''}
Workflow de Produção
${gerarWorkflowVisual(ordem)}
`;
} else {
modalBody.innerHTML = 'Ordem não encontrada
';
}
} catch (error) {
modalBody.innerHTML = `Erro ao carregar detalhes: ${error.message}
`;
}
}
// Gerar workflow visual igual ao da imagem
function gerarWorkflowVisual(ordem) {
const etapas = [
{ key: 'OrdemFabricacao', label: 'OF', valor: ordem.OrdemFabricacao },
{ key: 'AprovacaoLayout', label: 'Layout', valor: ordem.AprovacaoLayout },
{ key: 'LiberacaoListasMecanica', label: 'Lista Mecânica', valor: ordem.LiberacaoListasMecanica },
{ key: 'LiberacaoListasEletrica', label: 'Lista Elétrica', valor: ordem.LiberacaoListasEletrica },
{ key: 'Separacao', label: 'Separação', valor: ordem.Separacao },
{ key: 'PreMontagemEletrica', label: 'Pré-Montagem Elétrica', valor: ordem.PreMontagemEletrica, sublabel: true },
{ key: 'PreMontagemMecanica', label: 'Pré-Montagem Mecânica', valor: ordem.PreMontagemMecanica, sublabel: true },
{ key: 'PreMontagemPainel', label: 'Painel Elétrico', valor: ordem.PreMontagemPainel },
{ key: 'EletricaMontagem', label: 'Cabeamento', valor: ordem.EletricaMontagem },
{ key: 'Testes', label: 'Testes', valor: ordem.Testes },
{ key: 'FAT', label: 'FAT', valor: ordem.FAT },
{ key: 'PreparacaoExpedicao', label: 'Preparação Expedição', valor: ordem.PreparacaoExpedicao }
];
let html = `
Comessa: ${ordem.idOF} | Matricula: ${ordem.Matricula}
`;
etapas.forEach((etapa, index) => {
const concluida = etapa.valor === 1;
const emAndamento = index > 0 && etapas[index - 1].valor === 1 && !concluida;
let statusClass = '';
let statusColor = '';
if (concluida) {
statusClass = 'concluida';
statusColor = '#28a745'; // Verde
} else if (emAndamento) {
statusClass = 'em-andamento';
statusColor = '#ffc107'; // Amarelo
} else {
statusClass = 'pendente';
statusColor = '#6c757d'; // Cinza
}
html += `
${etapa.sublabel ? etapa.label : `${etapa.label} `}
`;
});
html += '
';
// Adicionar estilos CSS para o workflow
html += `
`;
return html;
}
// Relatórios
async function carregarRelatorios(container) {
container.innerHTML = `
Relatórios do Sistema PELL
Relatório do status das etapas do workflow de produção.
Período (dias):
Todos os registros
Últimos 30 dias
Últimos 60 dias
Últimos 90 dias
Gerar Relatório
Em Desenvolvimento: O relatório de cartão de ponto está sendo preparado com as particularidades específicas do sistema.
Este relatório mostrará dados detalhados de ponto dos funcionários por comessa, incluindo horas trabalhadas, períodos e totalizações.
`;
}
// Funções para gerar relatórios
async function gerarRelatorioOrdensPeriodo() {
const dataInicio = document.getElementById('dataInicio').value;
const dataFim = document.getElementById('dataFim').value;
const empresa = document.getElementById('empresaFiltro').value;
const container = document.getElementById('resultado-relatorio');
container.innerHTML = `
`;
try {
const params = new URLSearchParams();
if (dataInicio) params.append('data_inicio', dataInicio);
if (dataFim) params.append('data_fim', dataFim);
if (empresa) params.append('empresa', empresa);
const response = await apiRequest(`${API_BASE}/relatorios/ordens-periodo?${params}`);
const data = await response.json();
if (data.status === 'success') {
exibirRelatorioOrdensPeriodo(data, container);
} else {
throw new Error(data.message);
}
} catch (error) {
container.innerHTML = `
Erro ao gerar relatório: ${error.message}
`;
}
}
async function gerarRelatorioOrdensEmpresa() {
const empresa = document.getElementById('empresaRelatorio').value;
const container = document.getElementById('resultado-relatorio');
container.innerHTML = `
`;
try {
const params = new URLSearchParams();
if (empresa) params.append('empresa', empresa);
const response = await apiRequest(`${API_BASE}/relatorios/ordens-empresa?${params}`);
const data = await response.json();
if (data.status === 'success') {
exibirRelatorioOrdensEmpresa(data, container);
} else {
throw new Error(data.message);
}
} catch (error) {
container.innerHTML = `
Erro ao gerar relatório: ${error.message}
`;
}
}
async function gerarRelatorioWorkflow() {
const periodo = document.getElementById('periodoWorkflow').value;
const container = document.getElementById('resultado-relatorio');
container.innerHTML = `
`;
try {
const params = new URLSearchParams();
if (periodo) params.append('periodo', periodo);
const response = await apiRequest(`${API_BASE}/relatorios/workflow-status?${params}`);
const data = await response.json();
if (data.status === 'success') {
exibirRelatorioWorkflow(data, container);
} else {
throw new Error(data.message);
}
} catch (error) {
container.innerHTML = `
Erro ao gerar relatório: ${error.message}
`;
}
}
async function gerarRelatorioComessas() {
const codigo = document.getElementById('codigoComessa').value;
const container = document.getElementById('resultado-relatorio');
container.innerHTML = `
`;
try {
const params = new URLSearchParams();
if (codigo) params.append('codigo_comessa', codigo);
const response = await apiRequest(`${API_BASE}/relatorios/comessas?${params}`);
const data = await response.json();
if (data.status === 'success') {
exibirRelatorioComessas(data, container);
} else {
throw new Error(data.message);
}
} catch (error) {
container.innerHTML = `
Erro ao gerar relatório: ${error.message}
`;
}
}
// Materiais (placeholder)
async function carregarMateriais(container) {
container.innerHTML = `
Módulo de materiais em desenvolvimento. Esta seção permitirá visualizar o estoque e informações dos materiais.
`;
}
// Relatórios
async function carregarRelatorios(container) {
container.innerHTML = `
Relatórios do Sistema PELL
Sistema em Modo Somente Leitura: Este sistema está conectado ao banco de dados de produção para visualização apenas.
Relatórios de Cartão de Ponto
Por Comessa
Filtrar por número da comessa
Filtrar
Por Nome
Filtrar por nome do funcionário
Filtrar
Por Nome e Data
Filtrar por funcionário e período
Filtrar
Por Data
Filtrar por período
Filtrar
Por Comessa e Data
Filtrar por comessa e período
Filtrar
Por Comessa e Funcionário
Filtrar por comessa e funcionário
Filtrar
Cartão de Ponto
Relatório de horas por comessa
Visualizar
Lista de Comessas
Todas as comessas disponíveis
Visualizar
Funcionários
Lista de funcionários cadastrados
Visualizar
Estatísticas
Estatísticas gerais do sistema
Visualizar
Selecione um relatório acima para visualizar os dados.
`;
}
// Mostrar relatório de cartão de ponto
async function mostrarRelatorioCartaoPonto() {
const container = document.getElementById('conteudo-relatorio');
container.innerHTML = `
Selecione uma matrícula e clique em "Gerar Relatório"
`;
// Carregar lista de comessas
await carregarComessasSelect();
}
// Carregar comessas no select
async function carregarComessasSelect() {
try {
const response = await apiRequest(`${API_BASE}/relatorios/comessas`);
const data = await response.json();
const select = document.getElementById('matriculaRelatorio');
if (data.status === 'success') {
select.innerHTML = 'Selecione uma matrícula... ';
data.data.forEach(comessa => {
select.innerHTML += `${comessa.Matricula} (${comessa.total_registros} registros) `;
});
} else {
select.innerHTML = 'Erro ao carregar comessas ';
}
} catch (error) {
document.getElementById('matriculaRelatorio').innerHTML = 'Erro ao carregar ';
}
}
// Gerar relatório de cartão de ponto
async function gerarRelatorioCartaoPonto() {
const matricula = document.getElementById('matriculaRelatorio').value;
const dataInicio = document.getElementById('dataInicio').value;
const dataFim = document.getElementById('dataFim').value;
const container = document.getElementById('resultado-relatorio');
if (!matricula) {
mostrarErro('Selecione uma matrícula para gerar o relatório');
return;
}
container.innerHTML = `
Gerando relatório...
Gerando relatório...
`;
try {
const params = new URLSearchParams();
if (dataInicio) params.append('dataInicio', dataInicio);
if (dataFim) params.append('dataFim', dataFim);
const response = await apiRequest(`${API_BASE}/relatorios/cartao-ponto/${matricula}?${params}`);
const data = await response.json();
if (data.status === 'success') {
exibirRelatorioCartaoPonto(data.dados);
} else {
throw new Error(data.message);
}
} catch (error) {
container.innerHTML = `Erro ao gerar relatório: ${error.message}
`;
}
}
// Exibir relatório de cartão de ponto
function exibirRelatorioCartaoPonto(dados) {
const container = document.getElementById('resultado-relatorio');
if (dados.registros.length === 0) {
container.innerHTML = `
Nenhum registro encontrado para a matrícula ${dados.matricula} no período de
${formatarData(dados.periodo.inicio)} a ${formatarData(dados.periodo.fim)}
`;
return;
}
container.innerHTML = `
Nome
Data
Matrícula
Serviço
Início
Fim
Especificar
Total Minutos
Total Horas
${dados.registros.map(registro => `
${registro.Nome || '-'}
${formatarData(registro.Data)}
${registro.Matricula}
${registro.Servico || '-'}
${registro.Inicio || '-'}
${registro.Fim || '-'}
${registro.Especificar || '-'}
${registro.total_minutos || 0}
${registro.total_horas || '-'}
`).join('')}
TOTAL:
${dados.totais.total_minutos}
${dados.totais.total_horas_formatado}
Exportar para Excel
Imprimir
`;
}
// Lista de comessas
async function mostrarListaComessas() {
const container = document.getElementById('conteudo-relatorio');
container.innerHTML = `
`;
try {
const response = await apiRequest(`${API_BASE}/relatorios/comessas`);
const data = await response.json();
if (data.status === 'success') {
container.innerHTML = `
Matrícula
Total de Registros
Primeira Data
Última Data
Ações
${data.data.map(comessa => `
${comessa.Matricula}
${comessa.total_registros}
${formatarData(comessa.primeira_data)}
${formatarData(comessa.ultima_data)}
Ver Relatório
`).join('')}
`;
} else {
throw new Error(data.message);
}
} catch (error) {
container.innerHTML = `Erro ao carregar comessas: ${error.message}
`;
}
}
// Função para mostrar relatório por comessa
async function mostrarRelatorioPorComessa() {
const container = document.getElementById('conteudo-relatorio');
container.innerHTML = `
`;
}
async function gerarRelatorioPorComessa(event) {
event.preventDefault();
const comessa = document.getElementById('comessa').value;
const container = document.getElementById('resultado-relatorio');
try {
container.innerHTML = '';
const response = await apiRequest(`${API_BASE}/relatorios/por-comessa?comessa=${comessa}`);
const data = await response.json();
if (data.status === 'success') {
exibirRelatorioGenerico(data, container);
} else {
throw new Error(data.message);
}
} catch (error) {
container.innerHTML = `Erro: ${error.message}
`;
}
}
// Função para mostrar relatório por nome
async function mostrarRelatorioPorNome() {
const container = document.getElementById('conteudo-relatorio');
container.innerHTML = `
`;
}
async function gerarRelatorioPorNome(event) {
event.preventDefault();
const nome = document.getElementById('nome').value;
const container = document.getElementById('resultado-relatorio');
try {
container.innerHTML = '';
const response = await apiRequest(`${API_BASE}/relatorios/por-nome?nome=${encodeURIComponent(nome)}`);
const data = await response.json();
if (data.status === 'success') {
exibirRelatorioGenerico(data, container);
} else {
throw new Error(data.message);
}
} catch (error) {
container.innerHTML = `Erro: ${error.message}
`;
}
}
// Função para mostrar relatório por nome e data
async function mostrarRelatorioPorNomeData() {
const hoje = new Date().toISOString().split('T')[0];
const semanaAtras = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString().split('T')[0];
const container = document.getElementById('conteudo-relatorio');
container.innerHTML = `
`;
}
async function gerarRelatorioPorNomeData(event) {
event.preventDefault();
const nome = document.getElementById('nomeData').value;
const dataInicio = document.getElementById('dataInicio').value;
const dataFim = document.getElementById('dataFim').value;
const container = document.getElementById('resultado-relatorio');
try {
container.innerHTML = '';
const params = new URLSearchParams({
nome: nome,
dataInicio: dataInicio,
dataFim: dataFim
});
const response = await fetch(`${API_BASE}/relatorios/por-nome-data?${params}`);
const data = await response.json();
if (data.status === 'success') {
exibirRelatorioGenerico(data, container);
} else {
throw new Error(data.message);
}
} catch (error) {
container.innerHTML = `Erro: ${error.message}
`;
}
}
// Função para mostrar relatório por data
async function mostrarRelatorioPorData() {
const hoje = new Date().toISOString().split('T')[0];
const semanaAtras = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString().split('T')[0];
const container = document.getElementById('conteudo-relatorio');
container.innerHTML = `
`;
}
async function gerarRelatorioPorData(event) {
event.preventDefault();
const dataInicio = document.getElementById('dataInicioData').value;
const dataFim = document.getElementById('dataFimData').value;
const container = document.getElementById('resultado-relatorio');
try {
container.innerHTML = '';
const params = new URLSearchParams({
dataInicio: dataInicio,
dataFim: dataFim
});
const response = await fetch(`${API_BASE}/relatorios/por-data?${params}`);
const data = await response.json();
if (data.status === 'success') {
exibirRelatorioGenerico(data, container);
} else {
throw new Error(data.message);
}
} catch (error) {
container.innerHTML = `Erro: ${error.message}
`;
}
}
// Função para mostrar relatório por comessa e data
async function mostrarRelatorioPorComessaData() {
const hoje = new Date().toISOString().split('T')[0];
const semanaAtras = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString().split('T')[0];
const container = document.getElementById('conteudo-relatorio');
container.innerHTML = `
`;
}
async function gerarRelatorioPorComessaData(event) {
event.preventDefault();
const comessa = document.getElementById('comessaData').value;
const dataInicio = document.getElementById('dataInicioComessaData').value;
const dataFim = document.getElementById('dataFimComessaData').value;
const container = document.getElementById('resultado-relatorio');
try {
container.innerHTML = '';
const params = new URLSearchParams({
comessa: comessa,
dataInicio: dataInicio,
dataFim: dataFim
});
const response = await fetch(`${API_BASE}/relatorios/por-comessa-data?${params}`);
const data = await response.json();
if (data.status === 'success') {
exibirRelatorioGenerico(data, container);
} else {
throw new Error(data.message);
}
} catch (error) {
container.innerHTML = `Erro: ${error.message}
`;
}
}
// Função para mostrar relatório por comessa e funcionário
async function mostrarRelatorioPorComessaFuncionario() {
const container = document.getElementById('conteudo-relatorio');
container.innerHTML = `
`;
}
async function gerarRelatorioPorComessaFuncionario(event) {
event.preventDefault();
const comessa = document.getElementById('comessaFunc').value;
const nome = document.getElementById('nomeFunc').value;
const container = document.getElementById('resultado-relatorio');
try {
container.innerHTML = '';
const params = new URLSearchParams({
comessa: comessa,
nome: nome
});
const response = await fetch(`${API_BASE}/relatorios/por-comessa-funcionario?${params}`);
const data = await response.json();
if (data.status === 'success') {
exibirRelatorioGenerico(data, container);
} else {
throw new Error(data.message);
}
} catch (error) {
container.innerHTML = `Erro: ${error.message}
`;
}
}
// Função genérica para exibir relatórios
function exibirRelatorioGenerico(data, container) {
if (!data.registros || data.registros.length === 0) {
container.innerHTML = `
Nenhum registro encontrado para os filtros informados.
`;
return;
}
let totalMinutos = 0;
data.registros.forEach(registro => {
if (registro.total_minutos) {
totalMinutos += registro.total_minutos;
}
});
const totalHoras = Math.floor(totalMinutos / 60);
const totalMinutosRestantes = totalMinutos % 60;
const totalFormatado = `${totalHoras}:${totalMinutosRestantes.toString().padStart(2, '0')}`;
container.innerHTML = `
Total de Horas Trabalhadas: ${totalFormatado}
Nome
Data
Matrícula
Serviço
Início
Fim
Horas
${data.registros.map(registro => `
${registro.Nome || '-'}
${new Date(registro.Data).toLocaleDateString('pt-BR')}
${registro.Matricula || '-'}
${registro.Servico || '-'}
${registro.Inicio || '-'}
${registro.Fim || '-'}
${registro.total_horas || '0:00'}
`).join('')}
`;
}
// Funcionários placeholder
async function mostrarRelatorioFuncionarios() {
const container = document.getElementById('conteudo-relatorio');
container.innerHTML = `
Relatório de funcionários em desenvolvimento.
`;
}
// Estatísticas placeholder
async function mostrarEstatisticas() {
const container = document.getElementById('conteudo-relatorio');
container.innerHTML = `
Estatísticas gerais em desenvolvimento.
`;
}
// Gerar relatório rápido
function gerarRelatorioRapido(matricula) {
// Mudar para aba de cartão de ponto e preencher automaticamente
mostrarRelatorioCartaoPonto().then(() => {
document.getElementById('matriculaRelatorio').value = matricula;
gerarRelatorioCartaoPonto();
});
}
// Funções de exportação e impressão (placeholder)
function exportarRelatorio(matricula) {
mostrarSucesso('Funcionalidade de exportação em desenvolvimento');
}
function imprimirRelatorio() {
window.print();
}
// Utilitários
function formatarData(data) {
if (!data) return '-';
try {
return new Date(data).toLocaleDateString('pt-BR');
} catch (error) {
return '-';
}
}
function mostrarErro(mensagem) {
const alert = document.createElement('div');
alert.className = 'alert alert-danger alert-dismissible fade show';
alert.innerHTML = `
${mensagem}
`;
document.body.insertBefore(alert, document.body.firstChild);
setTimeout(() => {
alert.remove();
}, 5000);
}
function mostrarSucesso(mensagem) {
const alert = document.createElement('div');
alert.className = 'alert alert-success alert-dismissible fade show';
alert.innerHTML = `
${mensagem}
`;
document.body.insertBefore(alert, document.body.firstChild);
setTimeout(() => {
alert.remove();
}, 3000);
}
// WhatsApp - Sistema de Notificações
async function carregarWhatsApp(container) {
container.innerHTML = `
Sistema de Notificações WhatsApp
Sistema para envio automático de notificações sobre mudanças no workflow de produção.
Status da Conexão
Atualizar
Contatos Cadastrados
-
Ver Contatos
Inicializar WhatsApp
Conectar
Selecione uma ação acima para começar.
`;
// Carregar status inicial
await verificarStatusWhatsApp();
await carregarEstatisticas();
}
async function verificarStatusWhatsApp() {
try {
const response = await apiRequest(`${API_BASE}/whatsapp/status`);
const data = await response.json();
const statusDiv = document.getElementById('status-whatsapp');
if (data.whatsapp.conectado) {
statusDiv.innerHTML = '✅ Conectado ';
} else if (data.whatsapp.inicializando) {
statusDiv.innerHTML = '🔄 Inicializando... ';
} else {
statusDiv.innerHTML = '❌ Desconectado ';
}
} catch (error) {
document.getElementById('status-whatsapp').innerHTML = '❌ Erro ';
}
}
async function carregarEstatisticas() {
try {
const response = await apiRequest(`${API_BASE}/whatsapp/estatisticas`);
const data = await response.json();
if (data.status === 'success') {
const stats = data.estatisticas;
document.getElementById('total-contatos').innerHTML = `${stats.contatos_ativos}/${stats.total_contatos}`;
document.getElementById('estatisticas-whatsapp').innerHTML = `Hoje: ${stats.enviados_hoje} ✅ ${stats.erros_hoje} ❌`;
}
} catch (error) {
console.error('Erro ao carregar estatísticas:', error);
}
}
async function inicializarWhatsApp() {
try {
const response = await apiRequest(`${API_BASE}/whatsapp/inicializar`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' }
});
const data = await response.json();
alert(data.message);
if (data.status === 'success') {
document.getElementById('conteudo-whatsapp').innerHTML = `
QR Code para Conexão
Verifique o console do servidor para ver o QR Code e escaneie com seu WhatsApp.
Importante: O QR Code aparece no terminal onde o servidor está rodando.
`;
}
setTimeout(verificarStatusWhatsApp, 2000);
} catch (error) {
alert('Erro ao inicializar WhatsApp: ' + error.message);
}
}
async function mostrarTesteMessage() {
document.getElementById('conteudo-whatsapp').innerHTML = `
`;
}
async function enviarMensagemTeste(event) {
event.preventDefault();
const telefone = document.getElementById('telefone-teste').value;
const mensagem = document.getElementById('mensagem-teste').value;
const container = document.getElementById('resultado-teste');
try {
container.innerHTML = '';
const response = await apiRequest(`${API_BASE}/whatsapp/teste`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ telefone, mensagem })
});
const data = await response.json();
container.innerHTML = `
${data.message}
`;
} catch (error) {
container.innerHTML = `Erro: ${error.message}
`;
}
}
async function testarNotificacaoWorkflow() {
try {
const response = await apiRequest(`${API_BASE}/whatsapp/teste-workflow`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({})
});
const data = await response.json();
alert(data.message);
if (data.status === 'success') {
setTimeout(carregarEstatisticas, 2000);
}
} catch (error) {
alert('Erro ao testar notificação: ' + error.message);
}
}
async function listarContatos() {
try {
const response = await fetch(`${API_BASE}/whatsapp/contatos`);
const data = await response.json();
if (data.status === 'success') {
let html = `
Nome
Telefone
Tipo
Status
Cadastro
Ações
`;
data.contatos.forEach(contato => {
const statusBadge = contato.ativo ? 'success' : 'danger';
const statusText = contato.ativo ? 'Ativo' : 'Inativo';
const toggleText = contato.ativo ? 'Desativar' : 'Ativar';
const toggleIcon = contato.ativo ? 'pause' : 'play';
const toggleClass = contato.ativo ? 'warning' : 'success';
html += `
${contato.nome}
${contato.telefone}
${contato.tipo_notificacao}
${statusText}
${new Date(contato.data_cadastro).toLocaleDateString('pt-BR')}
`;
});
if (data.contatos.length === 0) {
html += `
Nenhum contato cadastrado
Adicionar Primeiro Contato
`;
}
html += `
`;
document.getElementById('conteudo-whatsapp').innerHTML = html;
}
} catch (error) {
document.getElementById('conteudo-whatsapp').innerHTML = `Erro: ${error.message}
`;
}
}
async function mostrarLogs() {
try {
const response = await fetch(`${API_BASE}/whatsapp/logs?limite=20`);
const data = await response.json();
if (data.status === 'success') {
let html = `
Data/Hora
Telefone
Mensagem
Status
`;
data.logs.forEach(log => {
html += `
${new Date(log.data_envio).toLocaleString('pt-BR')}
${log.telefone}
${log.mensagem.substring(0, 50)}...
${log.status}
`;
});
html += `
`;
document.getElementById('conteudo-whatsapp').innerHTML = html;
}
} catch (error) {
document.getElementById('conteudo-whatsapp').innerHTML = `Erro: ${error.message}
`;
}
}