PageSourceSearch

https://cmcoelhoneto.ma.gov.br/wp-content/plugins/obras-publicas/assets/js/obras-publicas.js?ver=1.0.5

js cmcoelhoneto.ma.gov.br collected 2026-10-08 02:05:50 UTC 17,415 bytes, 427 lines download raw bytes

1jQuery(document).ready(function($) {
2    // Configuração base do DataTable
3    const situacoesMap = {
4        'em_andamento': 'Em Andamento',
5        'paralisada': 'Paralisada',
6        'concluida': 'Concluída',
7        'cancelada': 'Cancelada',
8        'indevido': 'Indevido'
9    };
10
11    // Habilitar a busca para permitir os filtros personalizados
12    const baseConfig = {
13        language: {
14            emptyTable: "Nenhum registro encontrado",
15            info: "Mostrando de _START_ até _END_ de _TOTAL_ registros",
16            infoEmpty: "Mostrando 0 até 0 de 0 registros",
17            infoFiltered: "(Filtrados de _MAX_ registros)",
18            infoThousands: ".",
19            loadingRecords: "Carregando...",
20            processing: "Processando...",
21            zeroRecords: "Nenhum registro encontrado",
22            search: "Pesquisar",
23            paginate: {
24                next: "Próximo",
25                previous: "Anterior",
26                first: "Primeiro",
27                last: "Último"
28            },
29            buttons: {
30                excel: "Exportar Excel",
31                pdf: "Exportar PDF"
32            }
33        },
34        responsive: true,
35        searching: true, // Alterado para true para permitir filtros
36        dom: '<"top"B>rt<"bottom"ip>',
37        buttons: [
38            {
39                extend: 'excel',
40                text: 'Exportar Excel',
41                className: 'btn-export',
42                title: 'Obras Públicas'
43            },
44            {
45                extend: 'pdf',
46                text: 'Exportar PDF',
47                className: 'btn-export',
48                title: 'Obras Públicas',
49                orientation: 'landscape'
50            }
51        ],
52        pageLength: 10,
53        order: [[0, 'desc']],
54        columnDefs: [
55            {
56                targets: 8, // índice da coluna Situação
57                render: function(data, type, row) {
58                    return situacoesMap[data] || data;
59                }
60            }
61        ]
62    };
63
64    // Configuração específica para a tabela de obras
65    const obrasConfig = {
66        ...baseConfig,
67        columnDefs: [
68            {
69                targets: 1,
70                render: function(data, type, row) {
71                    if (type === 'display') {
72                        return '<span class="descricao-obra">' + data + '</span>';
73                    }
74                    return data;
75                }
76            },
77            {
78                targets: [3, 4], // Data Início e Previsão Término
79                render: function(data, type, row) {
80                    if (type === 'display' && data) {
81                        // Verificar se a data já está formatada (contém /)
82                        if (data.includes('/')) {
83                            return data;
84                        }
85                        
86                        try {
87                            const date = new Date(data);
88                            // Verificar se a data é válida
89                            if (isNaN(date.getTime())) {
90                                return '';
91                            }
92                            return date.toLocaleDateString('pt-BR');
93                        } catch (e) {
94                            return '';
95                        }
96                    }
97                    return data;
98                }
99            }
100        ]
101    };
102
103    // Configuração específica para a tabela de declarações
104    const declaracoesConfig = {
105        ...baseConfig,
106        columnDefs: [
107            {
108                targets: 2, // Índice da coluna de data de emissão
109                render: function(data, type, row) {
110                    // Para exibição (HTML), manter a data como está se já estiver formatada
111                    if (type === 'display' || type === 'filter') {
112                        // Se já estiver formatada com barras (vindo assim do PHP), não mexer
113                        if (data && data.includes('/')) {
114                            return data;
115                        }
116                        
117                        // Se estiver vazia, retornar vazia
118                        if (!data) {
119                            return '';
120                        }
121                        
122                        // Tentar converter para objeto Date e formatar
123                        try {
124                            const date = new Date(data);
125                            if (isNaN(date.getTime())) {
126                                return ''; // Data inválida
127                            }
128                            return date.toLocaleDateString('pt-BR');
129                        } catch (e) {
130                            return ''; // Erro ao processar a data
131                        }
132                    }
133                    return data;
134                }
135            }
136        ]
137    };
138
139    // Inicializar DataTables
140    const obrasTable = $('#obras-table').DataTable(obrasConfig);
141    const declaracoesTable = $('#declaracoes-table').DataTable(declaracoesConfig);
142
143    // Função para aplicar os filtros
144    function aplicarFiltros() {
145        const situacao = $('#filtro-situacao').val();
146        const descricao = $('#filtro-descricao').val().toLowerCase();
147        const empresa = $('#filtro-empresa').val().toLowerCase();
148        const ano = $('#filtro-ano').val();
149        const numero = $('#filtro-numero').val();
150
151        // Filtro customizado
152        $.fn.dataTable.ext.search.push(function(settings, data, dataIndex) {
153            if (settings.nTable.id !== 'obras-table') return true;
154
155            const row = {
156                intervencao: data[0].toLowerCase(),
157                descricao: $(data[1]).text().toLowerCase(),
158                empresa: data[2].toLowerCase(),
159                situacao: data[6]
160            };
161
162            // Verificar cada filtro
163            if (situacao && row.situacao !== situacoesMap[situacao]) return false;
164            if (descricao && !row.descricao.includes(descricao)) return false;
165            if (empresa && !row.empresa.includes(empresa)) return false;
166            
167            // Filtrar por ano e número da intervenção
168            if (ano || numero) {
169                const partes = row.intervencao.split('/');
170                if (partes.length === 2) {
171                    const [num, anoInt] = partes;
172                    if (ano && anoInt !== ano) return false;
173                    if (numero && !num.includes(numero)) return false;
174                }
175            }
176
177            return true;
178        });
179
180        // Redesenhar a tabela com os filtros aplicados
181        obrasTable.draw();
182
183        // Limpar o filtro customizado
184        $.fn.dataTable.ext.search.pop();
185    }
186
187    // Manipuladores de eventos para os filtros
188    $('#aplicar-filtros').on('click', function() {
189        aplicarFiltros();
190    });
191
192    $('#limpar-filtros').on('click', function() {
193        // Limpar todos os campos de filtro
194        $('#filtro-situacao').val('');
195        $('#filtro-descricao').val('');
196        $('#filtro-empresa').val('');
197        $('#filtro-ano').val('');
198        $('#filtro-numero').val('');
199
200        // Redesenhar a tabela sem filtros
201        obrasTable.search('').columns().search('').draw();
202    });
203
204    // Permitir filtrar ao pressionar Enter nos campos de texto
205    $('.filtro-grupo input').on('keypress', function(e) {
206        if (e.which === 13) {
207            aplicarFiltros();
208        }
209    });
210
211    // Manipulação das abas
212    $('.obras-publicas-tab').on('click', function() {
213        const target = $(this).data('target');
214        
215        // Atualizar abas ativas
216        $('.obras-publicas-tab').removeClass('active');
217        $(this).addClass('active');
218        
219        // Atualizar conteúdo ativo
220        $('.obras-publicas-content').removeClass('active');
221        $(`#${target}`).addClass('active');
222        
223        // Reajustar colunas das tabelas
224        if (target === 'obras-content') {
225            obrasTable.columns.adjust().responsive.recalc();
226        } else {
227            declaracoesTable.columns.adjust().responsive.recalc();
228        }
229    });
230
231    // Manipulação do modal
232    $(document).on('click', '.btn-detalhes-obra', function() {
233        const obraData = JSON.parse($(this).attr('data-obra'));
234        openModal(obraData);
235    });
236
237    // Função para abrir o modal
238    function openModal(data) {
239        const modalContent = `
240            <span class="obras-publicas-modal-close">&times;</span>
241            <h2>Detalhes da Obra</h2>
242            
243            <div class="modal-grid">
244                <div class="modal-section">
245                    <h3>Informações Gerais</h3>
246                    <p><strong>Intervenção/Ano:</strong> ${data.intervencao_ano}</p>
247                    <p><strong>Descrição:</strong> ${data.descricao_intervencao}</p>
248                    <p><strong>Empresa:</strong> ${data.empresa}</p>
249                    <p><strong>Objeto:</strong> ${data.objeto || 'Não informado'}</p>
250                    <p><strong>Bem(Imóvel):</strong> ${data.bem_imovel || 'Não informado'}</p>
251                    <p><strong>População atendida:</strong> ${data.populacao_atendida || 'Não informado'}</p>
252                </div>
253
254                <div class="modal-section">
255                    <h3>Datas e Prazos</h3>
256                    <p><strong>Data Início:</strong> ${data.data_inicio ? new Date(data.data_inicio).toLocaleDateString('pt-BR') : 'Não informado'}</p>
257                    <p><strong>Previsão Término:</strong> ${data.previsao_termino ? new Date(data.previsao_termino).toLocaleDateString('pt-BR') : 'Não informado'}</p>
258                    <p><strong>Ordem Serviço/Ano:</strong> ${data.ordem_servico_ano || 'Não informado'}</p>
259                    <p><strong>Situação:</strong> ${situacoesMap[data.situacao] || data.situacao}</p>
260                </div>
261
262                <div class="modal-section">
263                    <h3>Valores e Medições</h3>
264                    <p><strong>Valor Intervenção:</strong> ${data.valor_intervencao}</p>
265                    <p><strong>Valor Contrato:</strong> ${data.valor_contrato}</p>
266                    <p><strong>Valor Aditivo:</strong> ${data.valor_aditivo || 'Não informado'}</p>
267                    <p><strong>Medições:</strong> ${data.medicoes || 'Não informado'}</p>
268                    <p><strong>Percentual Empenhado:</strong> ${data.percentual_empenhado ? data.percentual_empenhado + '%' : 'Não informado'}</p>
269                </div>
270
271                <div class="modal-section">
272                    <h3>Responsáveis e Documentos</h3>
273                    <p><strong>Fiscal Técnico:</strong> ${data.fiscal_tecnico || 'Não informado'}</p>
274                    <p><strong>Contrato:</strong> ${data.link_contrato ? '<a href="' + data.link_contrato + '" target="_blank">Ver Contrato</a>' : 'Não disponível'}</p>
275                    ${data.anexos && data.anexos.length > 0 ? `
276                        <div class="anexos-lista">
277                            <h4>Anexos:</h4>
278                            <div class="anexos-grid">
279                                ${data.anexos.map(anexo => `
280                                    <a href="${anexo.arquivo_url}" target="_blank" class="btn-anexo">
281                                        <span class="dashicons dashicons-download"></span>
282                                        ${anexo.descricao}
283                                    </a>
284                                `).join('')}
285                            </div>
286                        </div>
287                    ` : ''}
288                </div>
289            </div>
290
291            <div class="obras-publicas-modal-buttons">
292                <button class="modal-export-btn excel" id="modal-export-excel">
293                    <span class="dashicons dashicons-media-spreadsheet"></span>
294                    Exportar Excel
295                </button>
296                <button class="modal-export-btn pdf" id="modal-export-pdf">
297                    <span class="dashicons dashicons-pdf"></span>
298                    Exportar PDF
299                </button>
300            </div>
301        `;
302
303        $('#obras-modal-content').html(modalContent);
304        $('#obras-modal').show();
305
306        // Adicionar eventos de clique para os botões de exportação
307        $('#modal-export-excel').on('click', function() {
308            const excelData = {
309                'Intervenção/Ano': data.intervencao_ano,
310                'Descrição': data.descricao_intervencao,
311                'Empresa': data.empresa,
312                'Data Início': data.data_inicio ? new Date(data.data_inicio).toLocaleDateString('pt-BR') : 'Não informado',
313                'Previsão Término': data.previsao_termino ? new Date(data.previsao_termino).toLocaleDateString('pt-BR') : 'Não informado',
314                'Valor Intervenção': data.valor_intervencao,
315                'Valor Contrato': data.valor_contrato,
316                'Valor Aditivo': data.valor_aditivo || 'Não informado',
317                'Situação': situacoesMap[data.situacao] || data.situacao,
318                'Ordem Serviço/Ano': data.ordem_servico_ano || 'Não informado',
319                'Medições': data.medicoes || 'Não informado',
320                'Percentual Empenhado': data.percentual_empenhado ? data.percentual_empenhado + '%' : 'Não informado',
321                'Bem(Imóvel)': data.bem_imovel || 'Não informado',
322                'Objeto': data.objeto || 'Não informado',
323                'População atendida': data.populacao_atendida || 'Não informado',
324                'Fiscal Técnico': data.fiscal_tecnico || 'Não informado'
325            };
326
327            // Criar e baixar arquivo Excel
328            const ws = XLSX.utils.json_to_sheet([excelData]);
329            const wb = XLSX.utils.book_new();
330            XLSX.utils.book_append_sheet(wb, ws, "Detalhes da Obra");
331            XLSX.writeFile(wb, `Obra_${data.intervencao_ano}.xlsx`);
332        });
333
334        $('#modal-export-pdf').on('click', function() {
335            const docDefinition = {
336                content: [
337                    { text: 'Detalhes da Obra', style: 'header' },
338                    { text: '\n' },
339                    { text: 'Informações Gerais', style: 'subheader' },
340                    { text: `Intervenção/Ano: ${data.intervencao_ano}` },
341                    { text: `Descrição: ${data.descricao_intervencao}` },
342                    { text: `Empresa: ${data.empresa}` },
343                    { text: '\n' },
344                    { text: 'Datas e Prazos', style: 'subheader' },
345                    { text: `Data Início: ${data.data_inicio ? new Date(data.data_inicio).toLocaleDateString('pt-BR') : 'Não informado'}` },
346                    { text: `Previsão Término: ${data.previsao_termino ? new Date(data.previsao_termino).toLocaleDateString('pt-BR') : 'Não informado'}` },
347                    { text: `Situação: ${situacoesMap[data.situacao] || data.situacao}` },
348                    { text: '\n' },
349                    { text: 'Valores e Medições', style: 'subheader' },
350                    { text: `Valor Intervenção: ${data.valor_intervencao}` },
351                    { text: `Valor Contrato: ${data.valor_contrato}` },
352                    { text: `Valor Aditivo: ${data.valor_aditivo || 'Não informado'}` },
353                    { text: `Percentual Empenhado: ${data.percentual_empenhado ? data.percentual_empenhado + '%' : 'Não informado'}` }
354                ],
355                styles: {
356                    header: {
357                        fontSize: 18,
358                        bold: true,
359                        margin: [0, 0, 0, 10]
360                    },
361                    subheader: {
362                        fontSize: 14,
363                        bold: true,
364                        margin: [0, 10, 0, 5]
365                    }
366                }
367            };
368
369            pdfMake.createPdf(docDefinition).download(`Obra_${data.intervencao_ano}.pdf`);
370        });
371    }
372
373    $(document).on('click', '.obras-publicas-modal-close', function() {
374        $('#obras-modal').hide();
375    });
376
377    $(window).on('click', function(event) {
378        if ($(event.target).is('#obras-modal')) {
379            $('#obras-modal').hide();
380        }
381    });
382
383    // Funções auxiliares
384    function formatMoney(value) {
385        if (!value) return '';
386        return new Intl.NumberFormat('pt-BR', {
387            minimumFractionDigits: 2,
388            maximumFractionDigits: 2
389        }).format(value);
390    }
391
392    function formatNumber(value) {
393        if (!value) return '';
394        return new Intl.NumberFormat('pt-BR').format(value);
395    }
396
397    function renderAnexos(anexos) {
398        if (!anexos || !anexos.length) {
399            return '<li>Nenhum anexo disponível</li>';
400        }
401
402        return anexos.map(anexo => `
403            <li>
404                <a href="${anexo.arquivo.url}" target="_blank">
405                    ${anexo.descricao} (${anexo.arquivo.filename})
406                </a>
407            </li>
408        `).join('');
409    }
410
411    // Funções de exportação
412    function exportPDF() {
413        // Implementar exportação PDF
414    }
415
416    function exportExcel() {
417        // Implementar exportação Excel
418    }
419
420    function exportJSON() {
421        // Implementar exportação JSON
422    }
423
424    function printDetails() {
425        window.print();
426    }
427}); 

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.