From 9ffc562357da3b706de16b0074cc481220dc72c3 Mon Sep 17 00:00:00 2001 From: andersonid Date: Fri, 4 Apr 2025 09:49:06 -0300 Subject: [PATCH] feat: implementa filtros e pesquisa AJAX na interface de militantes --- admin_qr.txt | 2 +- app.py | 3 +- static/js/militantes.js | 184 +++++++++++++++++++++++----------------- 3 files changed, 109 insertions(+), 80 deletions(-) diff --git a/admin_qr.txt b/admin_qr.txt index 8a51975..f5af4dd 100644 --- a/admin_qr.txt +++ b/admin_qr.txt @@ -1 +1 @@ -otpauth://totp/Sistema%20de%20Controles:admin?secret=7QGUNVWKH6TOSVZS5PK2KPPLJP4QW7QY&issuer=Sistema%20de%20Controles \ No newline at end of file +otpauth://totp/Sistema%20de%20Controles:admin?secret=NKUX7XZKAF6JOHO2NH6X23ZV64AQXEAX&issuer=Sistema%20de%20Controles \ No newline at end of file diff --git a/app.py b/app.py index f25012a..ff4077d 100644 --- a/app.py +++ b/app.py @@ -392,7 +392,8 @@ def listar_militantes(): db = get_db_connection() try: militantes = db.query(Militante).all() - return render_template('listar_militantes.html', militantes=militantes, Militante=Militante) + celulas = db.query(Celula).order_by(Celula.nome).all() + return render_template('listar_militantes.html', militantes=militantes, Militante=Militante, celulas=celulas) finally: db.close() diff --git a/static/js/militantes.js b/static/js/militantes.js index da765dc..b7e1e2a 100644 --- a/static/js/militantes.js +++ b/static/js/militantes.js @@ -1,40 +1,114 @@ console.log('Carregando script militantes.js...'); -function carregarDetalhesMilitante(id) { - // Pega o elemento clicado - const elemento = document.querySelector(`[data-militante-id="${id}"]`); - - // Preenche os campos do modal com os dados do data-attributes - document.getElementById('militanteNome').textContent = elemento.dataset.militanteNome; - document.getElementById('militanteCPF').textContent = elemento.dataset.militanteCpf; - document.getElementById('militanteEmail').textContent = elemento.dataset.militanteEmail; - document.getElementById('militanteTelefone').textContent = elemento.dataset.militanteTelefone; - document.getElementById('militanteEndereco').textContent = elemento.dataset.militanteEndereco; - document.getElementById('militanteFiliado').textContent = elemento.dataset.militanteFiliado === 'True' ? 'Filiado' : 'Não Filiado'; - - // Configura os botões de ação com o ID correto - const btnEditar = document.querySelector('#militanteModal .btn-primary'); - const btnExcluir = document.querySelector('#militanteModal .btn-danger'); - - // Atualiza o formulário de edição com o ID correto - const formEditar = document.getElementById('formEditarMilitante'); - if (formEditar) { - formEditar.action = `/militantes/editar/${id}`; - } - - // Atualiza o formulário de exclusão com o ID correto - const formExcluir = document.getElementById('deleteForm'); - if (formExcluir) { - formExcluir.action = `/militantes/excluir/${id}`; - } - - // Abre o modal - const modal = new bootstrap.Modal(document.getElementById('militanteModal')); - modal.show(); +// Variáveis globais para controle dos filtros +let filtroAtual = 'todos'; +let filtroResponsabilidade = null; +let filtroCelula = null; + +// Função para filtrar militantes +function filtrarMilitantes() { + const searchTerm = document.getElementById('searchInput').value.toLowerCase(); + const rows = document.querySelectorAll('#militantesTable tbody tr'); + let count = 0; + + rows.forEach(row => { + let shouldShow = true; + + // Filtro de texto + const textContent = row.textContent.toLowerCase(); + if (!textContent.includes(searchTerm)) { + shouldShow = false; + } + + // Filtro de status (filiado/não filiado) + if (filtroAtual !== 'todos') { + const filiado = row.getAttribute('data-filiado'); + if (filtroAtual === 'filiados' && filiado !== 'sim') { + shouldShow = false; + } + if (filtroAtual === 'nao-filiados' && filiado !== 'nao') { + shouldShow = false; + } + } + + // Filtro de responsabilidades + if (filtroResponsabilidade) { + const badges = row.querySelectorAll('.badge'); + const hasResponsabilidade = Array.from(badges).some(badge => + badge.textContent.toLowerCase() === filtroResponsabilidade.toLowerCase() + ); + if (!hasResponsabilidade) { + shouldShow = false; + } + } + + // Filtro de célula + if (filtroCelula) { + const celula = row.querySelector('[data-celula]').getAttribute('data-celula'); + if (celula !== filtroCelula) { + shouldShow = false; + } + } + + // Aplicar visibilidade + row.style.display = shouldShow ? '' : 'none'; + if (shouldShow) count++; + }); + + // Atualizar contador + document.getElementById('countMilitantes').textContent = count; } -// Função para preencher o modal de edição +// Configurar eventos quando o DOM estiver carregado document.addEventListener('DOMContentLoaded', function() { + // Configurar pesquisa + const searchInput = document.getElementById('searchInput'); + if (searchInput) { + let timeoutId; + searchInput.addEventListener('input', function() { + clearTimeout(timeoutId); + timeoutId = setTimeout(filtrarMilitantes, 300); + }); + } + + // Configurar filtros + document.querySelectorAll('.dropdown-item[data-filter]').forEach(item => { + item.addEventListener('click', function(e) { + e.preventDefault(); + + const filter = this.getAttribute('data-filter'); + const celula = this.getAttribute('data-celula'); + + // Resetar filtros anteriores + if (filter === 'todos') { + filtroAtual = 'todos'; + filtroResponsabilidade = null; + filtroCelula = null; + } else if (['filiados', 'nao-filiados'].includes(filter)) { + filtroAtual = filter; + filtroResponsabilidade = null; + filtroCelula = null; + } else if (['financas', 'imprensa', 'quadro-orientador'].includes(filter)) { + filtroAtual = 'todos'; + filtroResponsabilidade = filter === 'financas' ? 'Finanças' : + filter === 'imprensa' ? 'Imprensa' : + 'Quadro-Orientador'; + filtroCelula = null; + } else if (filter === 'celula') { + filtroAtual = 'todos'; + filtroResponsabilidade = null; + filtroCelula = celula; + } + + filtrarMilitantes(); + + // Atualizar texto do botão de filtro + const filterText = this.textContent; + const dropdownButton = document.querySelector('.dropdown-toggle'); + dropdownButton.innerHTML = `${filterText}`; + }); + }); + console.log('DOM carregado'); // Configuração do modal de edição @@ -310,52 +384,6 @@ document.addEventListener('DOMContentLoaded', function() { }); } - // Pesquisa em tempo real - const searchInput = document.getElementById('searchInput'); - if (searchInput) { - searchInput.addEventListener('input', function() { - const searchTerm = this.value.toLowerCase(); - const rows = document.querySelectorAll('#militantesTable tbody tr'); - let visibleCount = 0; - - rows.forEach(row => { - const text = row.textContent.toLowerCase(); - const isVisible = text.includes(searchTerm); - row.style.display = isVisible ? '' : 'none'; - if (isVisible) visibleCount++; - }); - - document.getElementById('countMilitantes').textContent = visibleCount; - }); - } - - // Filtros - const filterButtons = document.querySelectorAll('[data-filter]'); - filterButtons.forEach(button => { - button.addEventListener('click', function(e) { - e.preventDefault(); - const filter = this.getAttribute('data-filter'); - const rows = document.querySelectorAll('#militantesTable tbody tr'); - let visibleCount = 0; - - rows.forEach(row => { - const filiado = row.getAttribute('data-filiado'); - let isVisible = true; - - if (filter === 'filiados') { - isVisible = filiado === 'sim'; - } else if (filter === 'nao-filiados') { - isVisible = filiado === 'nao'; - } - - row.style.display = isVisible ? '' : 'none'; - if (isVisible) visibleCount++; - }); - - document.getElementById('countMilitantes').textContent = visibleCount; - }); - }); - // Ordenação const headers = document.querySelectorAll('#militantesTable th[data-sort]'); headers.forEach(header => {