feat: implementa filtros e pesquisa AJAX na interface de militantes

This commit is contained in:
andersonid
2025-04-04 09:49:06 -03:00
parent 3ed3002410
commit 9ffc562357
3 changed files with 109 additions and 80 deletions

View File

@@ -1 +1 @@
otpauth://totp/Sistema%20de%20Controles:admin?secret=7QGUNVWKH6TOSVZS5PK2KPPLJP4QW7QY&issuer=Sistema%20de%20Controles
otpauth://totp/Sistema%20de%20Controles:admin?secret=NKUX7XZKAF6JOHO2NH6X23ZV64AQXEAX&issuer=Sistema%20de%20Controles

3
app.py
View File

@@ -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()

View File

@@ -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}"]`);
// Variáveis globais para controle dos filtros
let filtroAtual = 'todos';
let filtroResponsabilidade = null;
let filtroCelula = null;
// 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';
// Função para filtrar militantes
function filtrarMilitantes() {
const searchTerm = document.getElementById('searchInput').value.toLowerCase();
const rows = document.querySelectorAll('#militantesTable tbody tr');
let count = 0;
// 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');
rows.forEach(row => {
let shouldShow = true;
// Atualiza o formulário de edição com o ID correto
const formEditar = document.getElementById('formEditarMilitante');
if (formEditar) {
formEditar.action = `/militantes/editar/${id}`;
}
// Filtro de texto
const textContent = row.textContent.toLowerCase();
if (!textContent.includes(searchTerm)) {
shouldShow = false;
}
// Atualiza o formulário de exclusão com o ID correto
const formExcluir = document.getElementById('deleteForm');
if (formExcluir) {
formExcluir.action = `/militantes/excluir/${id}`;
}
// 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;
}
}
// Abre o modal
const modal = new bootstrap.Modal(document.getElementById('militanteModal'));
modal.show();
// 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 = `<i class="fas fa-filter me-2"></i>${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 => {