feat: padroniza tela de pagamentos - Adiciona DataTables, modais e funcionalidades CRUD
This commit is contained in:
256
static/js/pagamentos.js
Normal file
256
static/js/pagamentos.js
Normal file
@@ -0,0 +1,256 @@
|
|||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
console.log('Carregando script pagamentos.js...');
|
||||||
|
|
||||||
|
// Inicializar DataTable
|
||||||
|
const table = $('#tabelaPagamentos').DataTable({
|
||||||
|
language: {
|
||||||
|
url: '//cdn.datatables.net/plug-ins/1.13.7/i18n/pt-BR.json'
|
||||||
|
},
|
||||||
|
order: [[3, 'desc']], // Ordenar por data de pagamento (decrescente)
|
||||||
|
columnDefs: [
|
||||||
|
{ targets: -1, orderable: false } // Desabilitar ordenação na coluna de ações
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
// Configuração do modal de edição
|
||||||
|
const modalEditarPagamento = document.getElementById('modalEditarPagamento');
|
||||||
|
if (modalEditarPagamento) {
|
||||||
|
modalEditarPagamento.addEventListener('show.bs.modal', function(event) {
|
||||||
|
console.log('Modal de edição sendo exibido');
|
||||||
|
const button = event.relatedTarget;
|
||||||
|
|
||||||
|
if (!button) {
|
||||||
|
console.error('Botão não encontrado!');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const pagamentoId = button.getAttribute('data-pagamento-id');
|
||||||
|
console.log('ID do pagamento:', pagamentoId);
|
||||||
|
|
||||||
|
// Dados do pagamento
|
||||||
|
const dados = {
|
||||||
|
militanteId: button.getAttribute('data-militante-id'),
|
||||||
|
militanteNome: button.closest('tr').querySelector('td').textContent.trim(),
|
||||||
|
tipoPagamento: button.getAttribute('data-tipo-pagamento'),
|
||||||
|
valor: button.getAttribute('data-valor'),
|
||||||
|
dataPagamento: button.getAttribute('data-data-pagamento')
|
||||||
|
};
|
||||||
|
console.log('Dados do pagamento:', dados);
|
||||||
|
|
||||||
|
// Preencher campos
|
||||||
|
document.getElementById('editMilitante').value = dados.militanteId;
|
||||||
|
document.getElementById('editMilitanteNome').value = dados.militanteNome;
|
||||||
|
document.getElementById('editTipoPagamento').value = dados.tipoPagamento;
|
||||||
|
document.getElementById('editValor').value = dados.valor;
|
||||||
|
document.getElementById('editDataPagamento').value = dados.dataPagamento;
|
||||||
|
|
||||||
|
// Configurar formulário
|
||||||
|
const form = document.getElementById('formEditarPagamento');
|
||||||
|
if (form) {
|
||||||
|
form.action = `/pagamentos/editar/${pagamentoId}`;
|
||||||
|
console.log('Action do formulário:', form.action);
|
||||||
|
|
||||||
|
// Remover listeners antigos para evitar duplicação
|
||||||
|
const newForm = form.cloneNode(true);
|
||||||
|
form.parentNode.replaceChild(newForm, form);
|
||||||
|
|
||||||
|
// Adicionar listener para o submit do formulário
|
||||||
|
newForm.addEventListener('submit', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
console.log('Formulário submetido');
|
||||||
|
|
||||||
|
// Criar FormData com os dados do formulário
|
||||||
|
const formData = new FormData(this);
|
||||||
|
|
||||||
|
// Log dos dados sendo enviados
|
||||||
|
console.log('Dados do formulário:');
|
||||||
|
for (let [key, value] of formData.entries()) {
|
||||||
|
console.log(key + ': ' + value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enviar requisição
|
||||||
|
fetch(this.action, {
|
||||||
|
method: 'POST',
|
||||||
|
body: formData
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
console.log('Status da resposta:', response.status);
|
||||||
|
return response.json();
|
||||||
|
})
|
||||||
|
.then(data => {
|
||||||
|
console.log('Resposta:', data);
|
||||||
|
if (data.status === 'success') {
|
||||||
|
// Fechar modal
|
||||||
|
const modal = bootstrap.Modal.getInstance(modalEditarPagamento);
|
||||||
|
modal.hide();
|
||||||
|
|
||||||
|
// Recarregar página
|
||||||
|
window.location.reload();
|
||||||
|
} else {
|
||||||
|
alert('Erro ao atualizar pagamento: ' + data.message);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Erro:', error);
|
||||||
|
alert('Erro ao atualizar pagamento. Por favor, tente novamente.');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configuração do modal de exclusão
|
||||||
|
const modalExcluirPagamento = document.getElementById('modalExcluirPagamento');
|
||||||
|
if (modalExcluirPagamento) {
|
||||||
|
modalExcluirPagamento.addEventListener('show.bs.modal', function(event) {
|
||||||
|
console.log('Modal de exclusão sendo exibido');
|
||||||
|
const button = event.relatedTarget;
|
||||||
|
|
||||||
|
if (!button) {
|
||||||
|
console.error('Botão não encontrado!');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const pagamentoId = button.getAttribute('data-pagamento-id');
|
||||||
|
const pagamentoInfo = button.getAttribute('data-pagamento-info');
|
||||||
|
console.log('ID do pagamento:', pagamentoId);
|
||||||
|
|
||||||
|
// Atualizar informações no modal
|
||||||
|
document.getElementById('pagamentoInfo').textContent = pagamentoInfo;
|
||||||
|
|
||||||
|
// Configurar formulário
|
||||||
|
const form = document.getElementById('formExcluirPagamento');
|
||||||
|
if (form) {
|
||||||
|
form.action = `/pagamentos/excluir/${pagamentoId}`;
|
||||||
|
console.log('Action do formulário:', form.action);
|
||||||
|
|
||||||
|
// Remover listeners antigos para evitar duplicação
|
||||||
|
const newForm = form.cloneNode(true);
|
||||||
|
form.parentNode.replaceChild(newForm, form);
|
||||||
|
|
||||||
|
// Adicionar listener para o submit do formulário
|
||||||
|
newForm.addEventListener('submit', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
console.log('Formulário submetido');
|
||||||
|
|
||||||
|
// Enviar requisição
|
||||||
|
fetch(this.action, {
|
||||||
|
method: 'POST'
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
console.log('Status da resposta:', response.status);
|
||||||
|
return response.json();
|
||||||
|
})
|
||||||
|
.then(data => {
|
||||||
|
console.log('Resposta:', data);
|
||||||
|
if (data.status === 'success') {
|
||||||
|
// Fechar modal
|
||||||
|
const modal = bootstrap.Modal.getInstance(modalExcluirPagamento);
|
||||||
|
modal.hide();
|
||||||
|
|
||||||
|
// Recarregar página
|
||||||
|
window.location.reload();
|
||||||
|
} else {
|
||||||
|
alert('Erro ao excluir pagamento: ' + data.message);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Erro:', error);
|
||||||
|
alert('Erro ao excluir pagamento. Por favor, tente novamente.');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configuração do formulário de novo pagamento
|
||||||
|
const formNovoPagamento = document.getElementById('formNovoPagamento');
|
||||||
|
if (formNovoPagamento) {
|
||||||
|
formNovoPagamento.addEventListener('submit', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
console.log('Formulário de novo pagamento submetido');
|
||||||
|
|
||||||
|
// Criar FormData com os dados do formulário
|
||||||
|
const formData = new FormData(this);
|
||||||
|
|
||||||
|
// Log dos dados sendo enviados
|
||||||
|
console.log('Dados do formulário:');
|
||||||
|
for (let [key, value] of formData.entries()) {
|
||||||
|
console.log(key + ': ' + value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enviar requisição
|
||||||
|
fetch(this.action, {
|
||||||
|
method: 'POST',
|
||||||
|
body: formData
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
console.log('Status da resposta:', response.status);
|
||||||
|
return response.json();
|
||||||
|
})
|
||||||
|
.then(data => {
|
||||||
|
console.log('Resposta:', data);
|
||||||
|
if (data.status === 'success') {
|
||||||
|
// Fechar modal
|
||||||
|
const modal = bootstrap.Modal.getInstance(document.getElementById('modalNovoPagamento'));
|
||||||
|
modal.hide();
|
||||||
|
|
||||||
|
// Recarregar página
|
||||||
|
window.location.reload();
|
||||||
|
} else {
|
||||||
|
alert('Erro ao adicionar pagamento: ' + data.message);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Erro:', error);
|
||||||
|
alert('Erro ao adicionar pagamento. Por favor, tente novamente.');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configuração do botão de exportar
|
||||||
|
const btnExportar = document.getElementById('btnExportar');
|
||||||
|
if (btnExportar) {
|
||||||
|
btnExportar.addEventListener('click', function() {
|
||||||
|
console.log('Exportando dados...');
|
||||||
|
|
||||||
|
// Coletar dados da tabela
|
||||||
|
const dados = [];
|
||||||
|
table.rows().every(function() {
|
||||||
|
const row = this.data();
|
||||||
|
dados.push({
|
||||||
|
militante: row[0],
|
||||||
|
tipo_pagamento: row[1],
|
||||||
|
valor: row[2].replace('R$ ', ''),
|
||||||
|
data_pagamento: row[3]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Converter para CSV
|
||||||
|
const csv = [
|
||||||
|
['Militante', 'Tipo de Pagamento', 'Valor', 'Data do Pagamento'],
|
||||||
|
...dados.map(row => [
|
||||||
|
row.militante,
|
||||||
|
row.tipo_pagamento,
|
||||||
|
row.valor,
|
||||||
|
row.data_pagamento
|
||||||
|
])
|
||||||
|
]
|
||||||
|
.map(row => row.join(','))
|
||||||
|
.join('\n');
|
||||||
|
|
||||||
|
// Criar blob e fazer download
|
||||||
|
const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
|
||||||
|
const link = document.createElement('a');
|
||||||
|
if (link.download !== undefined) {
|
||||||
|
const url = URL.createObjectURL(blob);
|
||||||
|
link.setAttribute('href', url);
|
||||||
|
link.setAttribute('download', 'pagamentos.csv');
|
||||||
|
link.style.visibility = 'hidden';
|
||||||
|
document.body.appendChild(link);
|
||||||
|
link.click();
|
||||||
|
document.body.removeChild(link);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -1,32 +1,203 @@
|
|||||||
{% extends 'base.html' %}
|
{% extends "base.html" %}
|
||||||
|
|
||||||
{% block title %}Listar Militantes{% endblock %}
|
{% block title %}Pagamentos{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h1>Pagamentos</h1>
|
<div class="container-fluid mt-3">
|
||||||
<a href="{{ url_for('novo_pagamento') }}">Adicionar Novo Pagamento</a>
|
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||||
<table border="1">
|
<h2><i class="fas fa-money-bill-wave"></i> Pagamentos</h2>
|
||||||
<thead>
|
<div>
|
||||||
<tr>
|
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#modalNovoPagamento">
|
||||||
<th>ID</th>
|
<i class="fas fa-plus"></i> Novo Pagamento
|
||||||
<th>Militante ID</th>
|
</button>
|
||||||
<th>Tipo de Pagamento</th>
|
<button type="button" class="btn btn-outline-primary" id="btnExportar">
|
||||||
<th>Valor</th>
|
<i class="fas fa-file-export"></i> Exportar
|
||||||
<th>Data do Pagamento</th>
|
</button>
|
||||||
</tr>
|
</div>
|
||||||
</thead>
|
</div>
|
||||||
<tbody>
|
|
||||||
{% for pagamento in pagamentos %}
|
<div class="card">
|
||||||
<tr>
|
<div class="card-body">
|
||||||
<td>{{ pagamento.id }}</td>
|
<div class="table-responsive">
|
||||||
<td>{{ pagamento.militante_id }}</td>
|
<table class="table table-striped table-hover" id="tabelaPagamentos">
|
||||||
<td>{{ pagamento.tipo_pagamento_id }}</td>
|
<thead>
|
||||||
<td>R$ {{ pagamento.valor }}</td>
|
<tr>
|
||||||
<td>{{ pagamento.data_pagamento }}</td>
|
<th>Militante</th>
|
||||||
</tr>
|
<th>Tipo de Pagamento</th>
|
||||||
{% endfor %}
|
<th>Valor</th>
|
||||||
</tbody>
|
<th>Data do Pagamento</th>
|
||||||
</table>
|
<th>Ações</th>
|
||||||
<a href="{{ url_for('home') }}">Home</a>
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for pagamento in pagamentos %}
|
||||||
|
<tr>
|
||||||
|
<td data-militante="{{ pagamento.militante_id }}">{{ pagamento.militante.nome if pagamento.militante else 'N/A' }}</td>
|
||||||
|
<td data-tipo="{{ pagamento.tipo_pagamento }}">
|
||||||
|
{% if pagamento.tipo_pagamento == 1 %}
|
||||||
|
Mensalidade
|
||||||
|
{% elif pagamento.tipo_pagamento == 2 %}
|
||||||
|
Contribuição Extra
|
||||||
|
{% elif pagamento.tipo_pagamento == 3 %}
|
||||||
|
Doação
|
||||||
|
{% elif pagamento.tipo_pagamento == 4 %}
|
||||||
|
Taxa de Evento
|
||||||
|
{% elif pagamento.tipo_pagamento == 5 %}
|
||||||
|
Outros
|
||||||
|
{% else %}
|
||||||
|
Não Definido
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td data-valor="{{ pagamento.valor }}">R$ {{ "%.2f"|format(pagamento.valor) }}</td>
|
||||||
|
<td data-data="{{ pagamento.data_pagamento }}">{{ pagamento.data_pagamento.strftime('%d/%m/%Y') }}</td>
|
||||||
|
<td>
|
||||||
|
<button type="button"
|
||||||
|
class="btn btn-sm btn-outline-primary"
|
||||||
|
data-bs-toggle="modal"
|
||||||
|
data-bs-target="#modalEditarPagamento"
|
||||||
|
data-pagamento-id="{{ pagamento.id }}"
|
||||||
|
data-militante-id="{{ pagamento.militante_id }}"
|
||||||
|
data-tipo-pagamento="{{ pagamento.tipo_pagamento }}"
|
||||||
|
data-valor="{{ pagamento.valor }}"
|
||||||
|
data-data-pagamento="{{ pagamento.data_pagamento.strftime('%Y-%m-%d') }}"
|
||||||
|
title="Editar">
|
||||||
|
<i class="fas fa-edit"></i>
|
||||||
|
</button>
|
||||||
|
<button type="button"
|
||||||
|
class="btn btn-sm btn-outline-danger"
|
||||||
|
data-bs-toggle="modal"
|
||||||
|
data-bs-target="#modalExcluirPagamento"
|
||||||
|
data-pagamento-id="{{ pagamento.id }}"
|
||||||
|
data-pagamento-info="Pagamento de {{ pagamento.militante.nome if pagamento.militante else 'N/A' }} - R$ {{ "%.2f"|format(pagamento.valor) }}"
|
||||||
|
title="Excluir">
|
||||||
|
<i class="fas fa-trash"></i>
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Modal Novo Pagamento -->
|
||||||
|
<div class="modal fade" id="modalNovoPagamento" tabindex="-1">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title"><i class="fas fa-plus"></i> Novo Pagamento</h5>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<form id="formNovoPagamento" method="post" action="{{ url_for('adicionar_pagamento') }}">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="militante" class="form-label">Militante:</label>
|
||||||
|
<select class="form-select" id="militante" name="militante_id" required>
|
||||||
|
<option value="">Selecione um militante</option>
|
||||||
|
{% for militante in militantes %}
|
||||||
|
<option value="{{ militante.id }}">{{ militante.nome }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="tipoPagamento" class="form-label">Tipo de Pagamento:</label>
|
||||||
|
<select class="form-select" id="tipoPagamento" name="tipo_pagamento" required>
|
||||||
|
<option value="">Selecione o tipo</option>
|
||||||
|
<option value="1">Mensalidade</option>
|
||||||
|
<option value="2">Contribuição Extra</option>
|
||||||
|
<option value="3">Doação</option>
|
||||||
|
<option value="4">Taxa de Evento</option>
|
||||||
|
<option value="5">Outros</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="valor" class="form-label">Valor:</label>
|
||||||
|
<input type="number" step="0.01" class="form-control" id="valor" name="valor" required>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="dataPagamento" class="form-label">Data do Pagamento:</label>
|
||||||
|
<input type="date" class="form-control" id="dataPagamento" name="data_pagamento" required>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancelar</button>
|
||||||
|
<button type="submit" class="btn btn-primary">Salvar</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Modal Editar Pagamento -->
|
||||||
|
<div class="modal fade" id="modalEditarPagamento" tabindex="-1">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title"><i class="fas fa-edit"></i> Editar Pagamento</h5>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<form id="formEditarPagamento" method="post">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="editMilitante" class="form-label">Militante:</label>
|
||||||
|
<input type="text" class="form-control bg-light" id="editMilitanteNome" readonly>
|
||||||
|
<input type="hidden" id="editMilitante" name="militante_id">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="editTipoPagamento" class="form-label">Tipo de Pagamento:</label>
|
||||||
|
<select class="form-select" id="editTipoPagamento" name="tipo_pagamento" required>
|
||||||
|
<option value="">Selecione o tipo</option>
|
||||||
|
<option value="1">Mensalidade</option>
|
||||||
|
<option value="2">Contribuição Extra</option>
|
||||||
|
<option value="3">Doação</option>
|
||||||
|
<option value="4">Taxa de Evento</option>
|
||||||
|
<option value="5">Outros</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="editValor" class="form-label">Valor:</label>
|
||||||
|
<input type="number" step="0.01" class="form-control" id="editValor" name="valor" required>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="editDataPagamento" class="form-label">Data do Pagamento:</label>
|
||||||
|
<input type="date" class="form-control" id="editDataPagamento" name="data_pagamento" required>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancelar</button>
|
||||||
|
<button type="submit" class="btn btn-primary">Salvar</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Modal Excluir Pagamento -->
|
||||||
|
<div class="modal fade" id="modalExcluirPagamento" tabindex="-1">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title"><i class="fas fa-trash"></i> Excluir Pagamento</h5>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<p>Tem certeza que deseja excluir este pagamento?</p>
|
||||||
|
<p id="pagamentoInfo" class="text-muted"></p>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<form id="formExcluirPagamento" method="post">
|
||||||
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancelar</button>
|
||||||
|
<button type="submit" class="btn btn-danger">Excluir</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block scripts %}
|
||||||
|
<script src="{{ url_for('static', filename='js/pagamentos.js') }}"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user