feat: implementada funcionalidade de exclusao de leads via API e botoes na interface (Kanban, Tabela Analitica e Modal)
This commit is contained in:
@@ -260,12 +260,13 @@ def export_leads():
|
||||
)
|
||||
|
||||
@leads_bp.route('/<lead_id>', methods=['DELETE'])
|
||||
@admin_required()
|
||||
@jwt_required()
|
||||
def delete_lead(lead_id):
|
||||
lead = db.session.get(Lead, lead_id)
|
||||
if not lead:
|
||||
return jsonify({'error': 'Lead não encontrado.'}), 404
|
||||
|
||||
LeadInteracao.query.filter_by(lead_id=lead.id).delete()
|
||||
db.session.delete(lead)
|
||||
db.session.commit()
|
||||
return jsonify({'message': f'Lead {lead.nome_empresa} excluído com sucesso.'}), 200
|
||||
|
||||
@@ -139,6 +139,18 @@ class APIClient:
|
||||
except Exception as e:
|
||||
return False, f"Erro: {str(e)}"
|
||||
|
||||
def delete_lead(self, lead_id: str) -> tuple[bool, str]:
|
||||
url = f"{self.base_url}/api/v1/leads/{lead_id}"
|
||||
try:
|
||||
with httpx.Client(timeout=10.0) as client:
|
||||
res = client.delete(url, headers=self._get_headers())
|
||||
data = res.json()
|
||||
if res.status_code == 200:
|
||||
return True, data.get('message', 'Lead excluído com sucesso.')
|
||||
return False, data.get('error', 'Erro ao excluir lead.')
|
||||
except Exception as e:
|
||||
return False, f"Erro ao comunicar com o servidor: {str(e)}"
|
||||
|
||||
def get_users(self) -> list:
|
||||
url = f"{self.base_url}/api/v1/users"
|
||||
try:
|
||||
|
||||
@@ -63,7 +63,7 @@ def render_kanban_board(leads: list, api_client: APIClient):
|
||||
if maps_url:
|
||||
st.markdown(f"[📍 Abrir no Google Maps]({maps_url})")
|
||||
|
||||
c1, c2 = st.columns([2, 1])
|
||||
c1, c2, c3 = st.columns([2, 1, 1])
|
||||
with c1:
|
||||
opts = [s[1] for s in STATUS_CONFIG]
|
||||
cur_idx = [s[0] for s in STATUS_CONFIG].index(status_key)
|
||||
@@ -80,6 +80,15 @@ def render_kanban_board(leads: list, api_client: APIClient):
|
||||
st.rerun()
|
||||
|
||||
with c2:
|
||||
if st.button("📝", key=f"btn_notes_{lead_id}", help="Editar notas e ver histórico"):
|
||||
if st.button("📝", key=f"btn_notes_{lead_id}", help="Editar notas e ver histórico", use_container_width=True):
|
||||
st.session_state['selected_lead_id'] = lead_id
|
||||
st.rerun()
|
||||
|
||||
with c3:
|
||||
if st.button("🗑️", key=f"btn_del_{lead_id}", help="Deletar lead permanentemente do banco", use_container_width=True):
|
||||
ok, msg = api_client.delete_lead(lead_id)
|
||||
if ok:
|
||||
st.toast(f"Lead '{nome}' excluído do banco!")
|
||||
else:
|
||||
st.error(msg)
|
||||
st.rerun()
|
||||
|
||||
@@ -88,19 +88,29 @@ def render_analytical_table_view(api_client: APIClient):
|
||||
)
|
||||
|
||||
st.markdown("### ⚙️ Ações Rápidas")
|
||||
col_sel, col_act = st.columns([2, 1])
|
||||
col_sel, col_opt, col_del = st.columns([2, 1, 1])
|
||||
with col_sel:
|
||||
selected_lead_id = st.selectbox(
|
||||
"Selecione um Lead para Ação LGPD:",
|
||||
"Selecione um Lead para Ação:",
|
||||
options=[l['id'] for l in filtered],
|
||||
format_func=lambda x: next((f"{l['nome_empresa']} ({l['status_funil']})" for l in filtered if l['id'] == x), x)
|
||||
)
|
||||
|
||||
with col_act:
|
||||
if st.button("🚫 Marcar Opt-Out (LGPD)", type="secondary", use_container_width=True):
|
||||
with col_opt:
|
||||
if st.button("🚫 Opt-Out (LGPD)", type="secondary", use_container_width=True):
|
||||
if selected_lead_id:
|
||||
api_client.opt_out_lead(selected_lead_id)
|
||||
st.success("Lead marcado como Opt-Out (Excluído / LGPD).")
|
||||
st.rerun()
|
||||
|
||||
with col_del:
|
||||
if st.button("🗑️ Deletar do Banco", type="primary", use_container_width=True):
|
||||
if selected_lead_id:
|
||||
ok, msg = api_client.delete_lead(selected_lead_id)
|
||||
if ok:
|
||||
st.success(msg)
|
||||
else:
|
||||
st.error(msg)
|
||||
st.rerun()
|
||||
else:
|
||||
st.info("Nenhum lead encontrado com os filtros selecionados.")
|
||||
|
||||
@@ -65,22 +65,32 @@ def render_lead_detail_modal(lead_id: str, api_client: APIClient):
|
||||
|
||||
new_notes = st.text_area("Notas / Observações Comerciais:", value=lead_detail.get('notas', ''), height=120)
|
||||
|
||||
c_save, c_opt, c_close = st.columns([1, 1, 1])
|
||||
c_save, c_opt, c_del, c_close = st.columns([1, 1, 1, 1])
|
||||
with c_save:
|
||||
if st.button("💾 Salvar Notas"):
|
||||
if st.button("💾 Salvar Notas", use_container_width=True):
|
||||
api_client.update_lead(lead_id, {'notas': new_notes})
|
||||
st.success("Notas atualizadas!")
|
||||
st.rerun()
|
||||
|
||||
with c_opt:
|
||||
if st.button("🚫 Opt-Out (LGPD)", help="Marcar lead para não contatar"):
|
||||
if st.button("🚫 Opt-Out (LGPD)", help="Marcar lead para não contatar", use_container_width=True):
|
||||
api_client.opt_out_lead(lead_id)
|
||||
st.warning("Lead marcado como Opt-Out LGPD.")
|
||||
st.session_state.pop('selected_lead_id', None)
|
||||
st.rerun()
|
||||
|
||||
with c_del:
|
||||
if st.button("🗑️ Deletar Lead", type="primary", help="Excluir lead permanentemente do banco", use_container_width=True):
|
||||
ok, msg = api_client.delete_lead(lead_id)
|
||||
if ok:
|
||||
st.success(msg)
|
||||
else:
|
||||
st.error(msg)
|
||||
st.session_state.pop('selected_lead_id', None)
|
||||
st.rerun()
|
||||
|
||||
with c_close:
|
||||
if st.button("❌ Fechar"):
|
||||
if st.button("❌ Fechar", use_container_width=True):
|
||||
st.session_state.pop('selected_lead_id', None)
|
||||
st.rerun()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user