diff --git a/static/js/militantes.js b/static/js/militantes.js new file mode 100644 index 0000000..da765dc --- /dev/null +++ b/static/js/militantes.js @@ -0,0 +1,419 @@ +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(); +} + +// Função para preencher o modal de edição +document.addEventListener('DOMContentLoaded', function() { + console.log('DOM carregado'); + + // Configuração do modal de edição + const modalEditarMilitante = document.getElementById('modalEditarMilitante'); + console.log('Modal de edição:', modalEditarMilitante); + + if (modalEditarMilitante) { + console.log('Modal encontrado, configurando eventos...'); + + modalEditarMilitante.addEventListener('show.bs.modal', function(event) { + console.log('Modal sendo exibido'); + const button = event.relatedTarget; + console.log('Botão:', button); + + if (!button) { + console.error('Botão não encontrado!'); + return; + } + + const militanteId = button.getAttribute('data-militante-id'); + console.log('ID do militante:', militanteId); + + // Dados do militante + const dados = { + nome: button.getAttribute('data-militante-nome'), + cpf: button.getAttribute('data-militante-cpf'), + email: button.getAttribute('data-militante-email'), + telefone: button.getAttribute('data-militante-telefone'), + endereco: button.getAttribute('data-militante-endereco'), + filiado: button.getAttribute('data-militante-filiado') + }; + console.log('Dados do militante:', dados); + + // Preencher campos + document.getElementById('editNome').value = dados.nome || ''; + document.getElementById('editCpf').value = dados.cpf || ''; + document.getElementById('editEmail').value = dados.email || ''; + document.getElementById('editTelefone').value = dados.telefone || ''; + document.getElementById('editEndereco').value = dados.endereco || ''; + document.getElementById('editFiliado').checked = dados.filiado === 'True'; + + // Configurar formulário + const form = document.getElementById('formEditarMilitante'); + if (form) { + form.action = `/militantes/editar/${militanteId}`; + console.log('Action do formulário:', form.action); + } + }); + + // Envio do formulário de edição via AJAX + const formEditarMilitante = document.getElementById('formEditarMilitante'); + if (formEditarMilitante) { + formEditarMilitante.addEventListener('submit', function(e) { + e.preventDefault(); + + const formData = new FormData(this); + + fetch(this.action, { + method: 'POST', + body: formData, + headers: { + 'X-Requested-With': 'XMLHttpRequest' + } + }) + .then(response => response.json()) + .then(data => { + if (data.status === 'success') { + // Fechar o modal + bootstrap.Modal.getInstance(modalEditarMilitante).hide(); + + // Atualizar a lista + location.reload(); + + // Mostrar mensagem de sucesso + const alertDiv = document.createElement('div'); + alertDiv.className = 'alert alert-success alert-dismissible fade show'; + alertDiv.innerHTML = ` + ${data.message} + + `; + document.querySelector('.container').insertBefore(alertDiv, document.querySelector('.container').firstChild); + } else { + // Mostrar erro + const alertDiv = document.createElement('div'); + alertDiv.className = 'alert alert-danger alert-dismissible fade show'; + alertDiv.innerHTML = ` + ${data.message} + + `; + document.querySelector('.modal-body').insertBefore(alertDiv, formEditarMilitante); + } + }) + .catch(error => { + console.error('Erro:', error); + const alertDiv = document.createElement('div'); + alertDiv.className = 'alert alert-danger alert-dismissible fade show'; + alertDiv.innerHTML = ` + Erro ao atualizar militante. Tente novamente. + + `; + document.querySelector('.modal-body').insertBefore(alertDiv, formEditarMilitante); + }); + }); + } + + // Limpar alertas quando o modal for fechado + modalEditarMilitante.addEventListener('hidden.bs.modal', function () { + const alerts = this.querySelectorAll('.alert'); + alerts.forEach(alert => alert.remove()); + }); + } else { + console.error('Modal de edição não encontrado!'); + } + + // Envio do formulário via AJAX + const formNovoMilitante = document.getElementById('formNovoMilitante'); + if (formNovoMilitante) { + formNovoMilitante.addEventListener('submit', function(e) { + e.preventDefault(); + + const formData = new FormData(this); + + fetch(this.action, { + method: 'POST', + body: formData, + headers: { + 'X-Requested-With': 'XMLHttpRequest' + } + }) + .then(response => response.json()) + .then(data => { + if (data.status === 'success') { + // Fechar o modal + const modal = bootstrap.Modal.getInstance(document.getElementById('modalNovoMilitante')); + modal.hide(); + + // Limpar o formulário + formNovoMilitante.reset(); + + // Adicionar o novo militante à tabela + const tbody = document.querySelector('#militantesTable tbody'); + const tr = document.createElement('tr'); + tr.setAttribute('data-militante', data.militante.id); + tr.setAttribute('data-filiado', data.militante.filiado ? 'sim' : 'nao'); + + tr.innerHTML = ` + ${data.militante.nome} + ${data.militante.cpf} + ${data.militante.email} + ${data.militante.telefone} + + + ${data.militante.filiado ? 'Sim' : 'Não'} + + + +
+ + +
+ + `; + + // Inserir no início da tabela + tbody.insertBefore(tr, tbody.firstChild); + + // Atualizar contador + const countElement = document.getElementById('countMilitantes'); + countElement.textContent = parseInt(countElement.textContent) + 1; + + // Mostrar mensagem de sucesso + const alertDiv = document.createElement('div'); + alertDiv.className = 'alert alert-success alert-dismissible fade show'; + alertDiv.innerHTML = ` + ${data.message} + + `; + document.querySelector('.container').insertBefore(alertDiv, document.querySelector('.container').firstChild); + } else { + // Mostrar erro + const alertDiv = document.createElement('div'); + alertDiv.className = 'alert alert-danger alert-dismissible fade show'; + alertDiv.innerHTML = ` + ${data.message} + + `; + document.querySelector('.modal-body').insertBefore(alertDiv, formNovoMilitante); + } + }) + .catch(error => { + console.error('Erro:', error); + // Mostrar erro genérico + const alertDiv = document.createElement('div'); + alertDiv.className = 'alert alert-danger alert-dismissible fade show'; + alertDiv.innerHTML = ` + Erro ao cadastrar militante. Tente novamente. + + `; + document.querySelector('.modal-body').insertBefore(alertDiv, formNovoMilitante); + }); + }); + } + + // Máscara para CPF + const cpfInput = document.getElementById('cpf'); + if (cpfInput) { + cpfInput.addEventListener('input', function(e) { + let value = e.target.value.replace(/\D/g, ''); + if (value.length <= 11) { + value = value.replace(/(\d{3})(\d{3})(\d{3})(\d{2})/, '$1.$2.$3-$4'); + e.target.value = value; + } + }); + } + + // Máscara para telefone + const telefoneInput = document.getElementById('telefone'); + if (telefoneInput) { + telefoneInput.addEventListener('input', function(e) { + let value = e.target.value.replace(/\D/g, ''); + if (value.length <= 11) { + if (value.length === 11) { + value = value.replace(/(\d{2})(\d{5})(\d{4})/, '($1) $2-$3'); + } else { + value = value.replace(/(\d{2})(\d{4})(\d{4})/, '($1) $2-$3'); + } + e.target.value = value; + } + }); + } + + // Limpar formulário e alertas quando o modal for fechado + const modalNovoMilitante = document.getElementById('modalNovoMilitante'); + if (modalNovoMilitante) { + modalNovoMilitante.addEventListener('hidden.bs.modal', function () { + formNovoMilitante.reset(); + const alerts = this.querySelectorAll('.alert'); + alerts.forEach(alert => alert.remove()); + }); + } + + // Configuração do modal de exclusão + const deleteModal = document.getElementById('deleteModal'); + if (deleteModal) { + deleteModal.addEventListener('show.bs.modal', function(event) { + const button = event.relatedTarget; + const militanteId = button.getAttribute('data-militante-id'); + const militanteNome = button.getAttribute('data-militante-nome'); + + document.getElementById('militanteNome').textContent = militanteNome; + document.getElementById('deleteForm').action = `/militantes/excluir/${militanteId}`; + }); + } + + // 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 => { + header.addEventListener('click', function() { + const column = this.getAttribute('data-sort'); + const tbody = document.querySelector('#militantesTable tbody'); + const rows = Array.from(tbody.querySelectorAll('tr')); + const isAsc = !this.classList.contains('sort-asc'); + + // Remover classes de ordenação de todos os headers + headers.forEach(h => { + h.classList.remove('sort-asc', 'sort-desc'); + h.querySelector('i').className = 'fas fa-sort'; + }); + + // Adicionar classe de ordenação ao header clicado + this.classList.add(isAsc ? 'sort-asc' : 'sort-desc'); + this.querySelector('i').className = `fas fa-sort-${isAsc ? 'up' : 'down'}`; + + // Ordenar linhas + rows.sort((a, b) => { + const aVal = a.querySelector(`td[data-${column}]`).getAttribute(`data-${column}`); + const bVal = b.querySelector(`td[data-${column}]`).getAttribute(`data-${column}`); + return isAsc ? aVal.localeCompare(bVal) : bVal.localeCompare(aVal); + }); + + // Reposicionar linhas + rows.forEach(row => tbody.appendChild(row)); + }); + }); + + // Exportar para CSV + const btnExportar = document.getElementById('btnExportar'); + if (btnExportar) { + btnExportar.addEventListener('click', function() { + const rows = document.querySelectorAll('#militantesTable tbody tr:not([style*="display: none"])'); + const headers = ['Nome', 'CPF', 'Email', 'Telefone', 'Filiado']; + let csv = headers.join(',') + '\n'; + + rows.forEach(row => { + const cols = row.querySelectorAll('td'); + const values = [ + cols[0].textContent, + cols[1].textContent, + cols[2].textContent, + cols[3].textContent, + cols[4].textContent.trim() + ].map(val => `"${val}"`); + csv += values.join(',') + '\n'; + }); + + const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' }); + const link = document.createElement('a'); + link.href = URL.createObjectURL(blob); + link.setAttribute('download', 'militantes.csv'); + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + }); + } +}); \ No newline at end of file diff --git a/templates/listar_militantes.html b/templates/listar_militantes.html index 32e1fbf..b0e911b 100644 --- a/templates/listar_militantes.html +++ b/templates/listar_militantes.html @@ -271,6 +271,7 @@ {% endblock %} {% block scripts %} +<<<<<<< HEAD +======= + +>>>>>>> 4b99410 (fix: corrige funcionamento do modal de edição de militantes - Corrige bloco de scripts e melhora tratamento de dados) {% endblock %} {% block extra_css %}