refactor: melhorias na interface e funcionalidades - Atualização do layout do dashboard com Bootstrap 5 - Remoção do template editar_pagamento.html (integrado ao modal) - Melhorias no template home.html com cards estatísticos - Ajustes nos estilos e responsividade - Correções nas rotas e conexões do banco de dados - Implementação do modal de edição de pagamentos - Adição de efeitos hover e melhorias visuais

This commit is contained in:
andersonid
2025-04-03 13:55:31 -03:00
parent 417b5c3f96
commit a28f543478
3 changed files with 275 additions and 64 deletions

107
app.py
View File

@@ -243,6 +243,7 @@ def home():
total_materiais = db.query(func.sum(MaterialVendido.valor)).scalar() or 0
total_assinaturas = db.query(func.sum(AssinaturaAnual.valor)).scalar() or 0
<<<<<<< HEAD
return render_template(
"home.html",
nome_usuario=nome_usuario,
@@ -252,6 +253,48 @@ def home():
total_materiais=total_materiais,
total_assinaturas=total_assinaturas
)
=======
# Buscar últimos militantes cadastrados
ultimos_militantes = db.query(Militante)\
.order_by(Militante.id.desc())\
.limit(5)\
.all()
# Buscar últimos pagamentos
ultimos_pagamentos = db.query(Pagamento)\
.join(Militante)\
.order_by(Pagamento.data_pagamento.desc())\
.limit(5)\
.all()
# Buscar tipos de pagamento
tipos_pagamento = db.query(TipoPagamento).all()
return render_template('home.html',
nome_usuario=nome_usuario,
data_atual=data_formatada,
total_militantes=total_militantes,
total_cotas="{:.2f}".format(total_cotas),
total_materiais=total_materiais,
total_assinaturas=total_assinaturas,
ultimos_militantes=ultimos_militantes,
ultimos_pagamentos=ultimos_pagamentos,
tipos_pagamento=tipos_pagamento)
except Exception as e:
print(f"Erro na página inicial: {e}")
import traceback
traceback.print_exc()
flash('Erro ao carregar a página inicial', 'danger')
return render_template('home.html',
nome_usuario="Usuário",
data_atual=datetime.now().strftime("%d/%m/%Y"),
total_militantes=0,
total_cotas="0.00",
total_materiais=0,
total_assinaturas=0,
ultimos_militantes=[],
ultimos_pagamentos=[])
>>>>>>> 324660d (refactor: melhorias na interface e funcionalidades - Atualização do layout do dashboard com Bootstrap 5 - Remoção do template editar_pagamento.html (integrado ao modal) - Melhorias no template home.html com cards estatísticos - Ajustes nos estilos e responsividade - Correções nas rotas e conexões do banco de dados - Implementação do modal de edição de pagamentos - Adição de efeitos hover e melhorias visuais)
finally:
db.close()
@@ -1275,6 +1318,7 @@ def toggle_quadro_orientador(user_id):
finally:
db.close()
<<<<<<< HEAD
@app.route('/usuarios/<int:user_id>/toggle_aspirante', methods=['POST'])
@require_login
def toggle_aspirante(user_id):
@@ -1477,6 +1521,69 @@ def session_timeout():
db_session.commit()
except Exception as e:
print(f"Erro ao atualizar última atividade: {e}")
=======
# API Routes para os modais
@app.route('/api/pagamentos/<int:id>', methods=['GET'])
@login_required
def get_pagamento(id):
db = get_db_connection()
try:
pagamento = db.query(Pagamento).get(id)
if not pagamento:
return jsonify({'success': False, 'message': 'Pagamento não encontrado'}), 404
return jsonify({
'id': pagamento.id,
'valor': pagamento.valor,
'data_pagamento': pagamento.data_pagamento.strftime('%Y-%m-%d'),
'tipo_pagamento_id': pagamento.tipo_pagamento_id,
'observacao': pagamento.observacao
})
finally:
db.close()
@app.route('/api/pagamentos/<int:id>', methods=['PUT'])
@login_required
def update_pagamento(id):
db = get_db_connection()
try:
pagamento = db.query(Pagamento).get(id)
if not pagamento:
return jsonify({'success': False, 'message': 'Pagamento não encontrado'}), 404
try:
pagamento.valor = float(request.form['valor'])
pagamento.data_pagamento = datetime.strptime(request.form['data_pagamento'], '%Y-%m-%d')
pagamento.tipo_pagamento_id = int(request.form['tipo_pagamento'])
pagamento.observacao = request.form['observacao']
db.commit()
return jsonify({'success': True})
except Exception as e:
db.rollback()
return jsonify({'success': False, 'message': str(e)}), 400
finally:
db.close()
@app.route('/api/pagamentos/<int:id>', methods=['DELETE'])
@login_required
def delete_pagamento(id):
db = get_db_connection()
try:
pagamento = db.query(Pagamento).get(id)
if not pagamento:
return jsonify({'success': False, 'message': 'Pagamento não encontrado'}), 404
try:
db.delete(pagamento)
db.commit()
return jsonify({'success': True})
except Exception as e:
db.rollback()
return jsonify({'success': False, 'message': str(e)}), 400
finally:
db.close()
>>>>>>> 324660d (refactor: melhorias na interface e funcionalidades - Atualização do layout do dashboard com Bootstrap 5 - Remoção do template editar_pagamento.html (integrado ao modal) - Melhorias no template home.html com cards estatísticos - Ajustes nos estilos e responsividade - Correções nas rotas e conexões do banco de dados - Implementação do modal de edição de pagamentos - Adição de efeitos hover e melhorias visuais)
def create_app():
app = Flask(__name__)

View File

@@ -1,60 +0,0 @@
{% extends "base.html" %}
{% block title %}Editar Pagamento{% endblock %}
{% block content %}
<div class="container mt-4">
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-header">
<h5 class="card-title mb-0">
<i class="fas fa-edit me-2"></i>Editar Pagamento
</h5>
</div>
<div class="card-body">
<form method="post">
<div class="row">
<div class="col-md-6 mb-3">
<label for="valor" class="form-label">Valor</label>
<div class="input-group">
<span class="input-group-text">R$</span>
<input type="number" step="0.01" class="form-control" id="valor" name="valor" value="{{ pagamento.valor }}" required>
</div>
</div>
<div class="col-md-6 mb-3">
<label for="data_pagamento" class="form-label">Data do Pagamento</label>
<input type="date" class="form-control" id="data_pagamento" name="data_pagamento" value="{{ pagamento.data_pagamento.strftime('%Y-%m-%d') }}" required>
</div>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label for="tipo_pagamento" class="form-label">Tipo de Pagamento</label>
<select class="form-select" id="tipo_pagamento" name="tipo_pagamento" required>
{% for tipo in tipos_pagamento %}
<option value="{{ tipo.id }}" {% if tipo.id == pagamento.tipo_pagamento_id %}selected{% endif %}>
{{ tipo.nome }}
</option>
{% endfor %}
</select>
</div>
<div class="col-md-6 mb-3">
<label for="observacao" class="form-label">Observação</label>
<textarea class="form-control" id="observacao" name="observacao" rows="3">{{ pagamento.observacao }}</textarea>
</div>
</div>
<div class="d-flex justify-content-end gap-2">
<a href="{{ url_for('listar_pagamentos') }}" class="btn btn-secondary">
<i class="fas fa-times me-2"></i>Cancelar
</a>
<button type="submit" class="btn btn-primary">
<i class="fas fa-save me-2"></i>Salvar Alterações
</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@@ -108,12 +108,31 @@
{% if ultimos_pagamentos %}
<div class="list-group list-group-flush">
{% for pagamento in ultimos_pagamentos %}
<div class="list-group-item" onclick="window.location='{{ url_for('editar_pagamento', id=pagamento.id) }}'">
<div class="list-group-item" style="cursor: pointer" onclick="carregarDadosPagamento({{ pagamento.id }})">
<div class="militante-info">
<h6 class="mb-1">{{ pagamento.militante.nome }}</h6>
<small>{{ pagamento.data_pagamento.strftime('%d/%m/%Y') }}</small>
</div>
<div class="d-flex align-items-center gap-2">
<span class="badge bg-success">R$ {{ "%.2f"|format(pagamento.valor) }}</span>
<div class="dropdown">
<button class="btn btn-link text-secondary p-0" type="button" data-bs-toggle="dropdown">
<i class="fas fa-ellipsis-v"></i>
</button>
<ul class="dropdown-menu dropdown-menu-end">
<li>
<a class="dropdown-item" href="#" onclick="event.stopPropagation(); carregarDadosPagamento({{ pagamento.id }})">
<i class="fas fa-edit me-2"></i>Editar
</a>
</li>
<li>
<a class="dropdown-item text-danger" href="#" onclick="event.stopPropagation(); confirmarExclusao({{ pagamento.id }}, 'pagamentos')">
<i class="fas fa-trash me-2"></i>Excluir
</a>
</li>
</ul>
</div>
</div>
</div>
{% endfor %}
</div>
@@ -226,21 +245,84 @@
</div>
</div>
<!-- Modal de Exclusão -->
<!-- Modal de Edição de Pagamento -->
<div class="modal fade" id="modalEditarPagamento" tabindex="-1">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">
<i class="fas fa-money-bill-wave me-2"></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">
<input type="hidden" id="editPagamentoId" name="id">
<div class="mb-3">
<label for="editValor" class="form-label">Valor</label>
<div class="input-group">
<span class="input-group-text">R$</span>
<input type="number" step="0.01" class="form-control" id="editValor" name="valor" required>
</div>
</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="mb-3">
<label for="editTipoPagamento" class="form-label">Tipo de Pagamento</label>
<select class="form-select" id="editTipoPagamento" name="tipo_pagamento" required>
{% for tipo in tipos_pagamento %}
<option value="{{ tipo.id }}">{{ tipo.nome }}</option>
{% endfor %}
</select>
</div>
<div class="mb-3">
<label for="editObservacao" class="form-label">Observação</label>
<textarea class="form-control" id="editObservacao" name="observacao" rows="3"></textarea>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
<i class="fas fa-times me-2"></i>Cancelar
</button>
<button type="submit" form="formEditarPagamento" class="btn btn-primary">
<i class="fas fa-save me-2"></i>Salvar Alterações
</button>
</div>
</div>
</div>
</div>
<!-- Modal de Confirmação de Exclusão -->
<div class="modal fade" id="deleteModal" tabindex="-1">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Confirmar Exclusão</h5>
<h5 class="modal-title">
<i class="fas fa-exclamation-triangle me-2"></i>Confirmar Exclusão
</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<<<<<<< HEAD
<p>Tem certeza que deseja excluir este militante?</p>
<p class="text-danger">Esta ação não pode ser desfeita.</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancelar</button>
<button type="button" class="btn btn-danger" id="confirmDelete">
=======
<p>Tem certeza que deseja excluir este item?</p>
<p class="text-danger"><small>Esta ação não pode ser desfeita.</small></p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
<i class="fas fa-times me-2"></i>Cancelar
</button>
<button type="button" class="btn btn-danger" id="btnConfirmarExclusao">
>>>>>>> 324660d (refactor: melhorias na interface e funcionalidades - Atualização do layout do dashboard com Bootstrap 5 - Remoção do template editar_pagamento.html (integrado ao modal) - Melhorias no template home.html com cards estatísticos - Ajustes nos estilos e responsividade - Correções nas rotas e conexões do banco de dados - Implementação do modal de edição de pagamentos - Adição de efeitos hover e melhorias visuais)
<i class="fas fa-trash me-2"></i>Excluir
</button>
</div>
@@ -350,5 +432,87 @@
deleteMilitante(id);
});
});
<<<<<<< HEAD
=======
// Função para carregar dados do pagamento no modal
function carregarDadosPagamento(id) {
fetch(`/api/pagamentos/${id}`)
.then(response => response.json())
.then(data => {
document.getElementById('editPagamentoId').value = data.id;
document.getElementById('editValor').value = data.valor;
document.getElementById('editDataPagamento').value = data.data_pagamento;
document.getElementById('editTipoPagamento').value = data.tipo_pagamento_id;
document.getElementById('editObservacao').value = data.observacao || '';
// Abre o modal
new bootstrap.Modal(document.getElementById('modalEditarPagamento')).show();
})
.catch(error => {
console.error('Erro ao carregar dados:', error);
alert('Erro ao carregar dados do pagamento');
});
}
// Função para salvar alterações do pagamento
document.getElementById('formEditarPagamento').addEventListener('submit', function(e) {
e.preventDefault();
const id = document.getElementById('editPagamentoId').value;
const formData = new FormData(this);
fetch(`/api/pagamentos/${id}`, {
method: 'PUT',
body: formData
})
.then(response => response.json())
.then(data => {
if (data.success) {
// Fecha o modal
bootstrap.Modal.getInstance(document.getElementById('modalEditarPagamento')).hide();
// Recarrega a página
location.reload();
} else {
alert('Erro ao salvar alterações: ' + data.message);
}
})
.catch(error => {
console.error('Erro ao salvar:', error);
alert('Erro ao salvar alterações');
});
});
// Configuração do modal de exclusão
let itemParaExcluir = null;
let tipoItem = null;
function confirmarExclusao(id, tipo) {
itemParaExcluir = id;
tipoItem = tipo;
new bootstrap.Modal(document.getElementById('deleteModal')).show();
}
document.getElementById('btnConfirmarExclusao').addEventListener('click', function() {
if (!itemParaExcluir || !tipoItem) return;
fetch(`/api/${tipoItem}/${itemParaExcluir}`, {
method: 'DELETE'
})
.then(response => response.json())
.then(data => {
if (data.success) {
location.reload();
} else {
alert('Erro ao excluir: ' + data.message);
}
})
.catch(error => {
console.error('Erro ao excluir:', error);
alert('Erro ao excluir item');
});
});
});
>>>>>>> 324660d (refactor: melhorias na interface e funcionalidades - Atualização do layout do dashboard com Bootstrap 5 - Remoção do template editar_pagamento.html (integrado ao modal) - Melhorias no template home.html com cards estatísticos - Ajustes nos estilos e responsividade - Correções nas rotas e conexões do banco de dados - Implementação do modal de edição de pagamentos - Adição de efeitos hover e melhorias visuais)
</script>
{% endblock %}