120 lines
6.3 KiB
Python
120 lines
6.3 KiB
Python
import pandas as pd
|
|
import streamlit as st
|
|
from api_client import APIClient
|
|
|
|
def render_radar_busca_view(api_client: APIClient):
|
|
st.title("📡 Radar de Prospecção Geolocalizada")
|
|
st.caption("Varra o Google Maps em tempo real por CEP e ramo de atividade. Selecione individualmente quais estabelecimentos deseja importar para a sua base de dados.")
|
|
|
|
c1, c2 = st.columns([1, 2])
|
|
|
|
with c1:
|
|
with st.container(border=True):
|
|
st.subheader("🔍 Parâmetros de Busca")
|
|
|
|
cep = st.text_input("CEP Alvo", value="01310-100", help="Digite o CEP com ou sem hífen (ex: 01310-100)")
|
|
|
|
ramo_sugestoes = [
|
|
"Clínica Odontológica", "Padaria", "Restaurante", "Academia",
|
|
"Escritório de Contabilidade", "Oficina Mecânica", "Farmácia", "Salão de Beleza"
|
|
]
|
|
ramo = st.selectbox("Ramo de Atividade", options=ramo_sugestoes, index=0)
|
|
custom_ramo = st.text_input("Ou digite um ramo personalizado:", value="", placeholder="Ex: Petshop 24h")
|
|
|
|
ramo_final = custom_ramo.strip() if custom_ramo.strip() else ramo
|
|
max_results = st.slider("Quantidade máxima de estabelecimentos", min_value=5, max_value=50, value=15, step=5)
|
|
|
|
if st.button("🛰️ Buscar no Google Maps", type="primary", use_container_width=True):
|
|
if not cep:
|
|
st.error("Informe um CEP válido.")
|
|
else:
|
|
st.session_state.pop('preview_data', None)
|
|
st.session_state.pop('import_success_msg', None)
|
|
|
|
progress_bar = st.progress(0, text="Iniciando triangulação de CEP via ViaCEP...")
|
|
|
|
with st.spinner("Navegando no Google Maps em tempo real via Playwright Chromium..."):
|
|
progress_bar.progress(40, text="Executando scraper headless e rolando feed de estabelecimentos...")
|
|
success, data = api_client.scrape_preview(cep, ramo_final, max_results)
|
|
progress_bar.progress(100, text="Varredura concluída!")
|
|
|
|
if success:
|
|
st.session_state['preview_data'] = data
|
|
st.session_state['search_cep'] = cep
|
|
st.session_state['search_ramo'] = ramo_final
|
|
else:
|
|
progress_bar.empty()
|
|
st.error(data.get('error', 'Falha ao executar varredura.'))
|
|
|
|
with c2:
|
|
# Se houver mensagem de sucesso da importação recente
|
|
if st.session_state.get('import_success_msg'):
|
|
st.success(st.session_state['import_success_msg'])
|
|
|
|
preview_data = st.session_state.get('preview_data')
|
|
if preview_data:
|
|
results = preview_data.get('results', [])
|
|
location = preview_data.get('location', {})
|
|
count = preview_data.get('count', 0)
|
|
|
|
st.subheader(f"📋 Estabelecimentos Encontrados ({count})")
|
|
st.caption(f"📍 **Localização:** {location.get('bairro', 'Bairro')}, {location.get('cidade', 'Cidade')}-{location.get('uf', '')} | Query: `{preview_data.get('search_query')}`")
|
|
|
|
if not results:
|
|
st.warning("Nenhum estabelecimento foi encontrado no Google Maps para esta combinação de CEP e Ramo.")
|
|
else:
|
|
st.write("Marque as caixas de seleção abaixo para escolher quais leads deseja salvar no banco de dados:")
|
|
|
|
# Tabela com checkboxes de seleção individual
|
|
df_preview = pd.DataFrame([
|
|
{
|
|
'Importar': True,
|
|
'Empresa': r.get('nome_empresa'),
|
|
'Telefone': r.get('telefone') or 'Não informado',
|
|
'Avaliação': f"⭐ {r.get('google_rating')} ({r.get('total_avaliacoes')})",
|
|
'Endereço / Trecho': r.get('endereco', ''),
|
|
'_raw_item': r
|
|
}
|
|
for r in results
|
|
])
|
|
|
|
edited_df = st.data_editor(
|
|
df_preview.drop(columns=['_raw_item']),
|
|
column_config={
|
|
"Importar": st.column_config.CheckboxColumn("Importar?", default=True)
|
|
},
|
|
disabled=["Empresa", "Telefone", "Avaliação", "Endereço / Trecho"],
|
|
use_container_width=True,
|
|
hide_index=True
|
|
)
|
|
|
|
# Identificar os itens marcados para importação
|
|
selected_indices = edited_df[edited_df["Importar"]].index.tolist()
|
|
selected_items = [results[i] for i in selected_indices if i < len(results)]
|
|
|
|
st.write(f"**Leads selecionados para importação:** {len(selected_items)} de {len(results)}")
|
|
|
|
btn_c1, btn_c2 = st.columns([2, 1])
|
|
with btn_c1:
|
|
if st.button(f"💾 Salvar {len(selected_items)} Lead(s) Selecionado(s) no Banco", type="primary", use_container_width=True, disabled=len(selected_items) == 0):
|
|
with st.spinner("Persistindo e deduplicando leads selecionados no banco..."):
|
|
imp_success, imp_msg = api_client.import_selected_leads(
|
|
st.session_state.get('search_cep', cep),
|
|
st.session_state.get('search_ramo', ramo_final),
|
|
selected_items
|
|
)
|
|
if imp_success:
|
|
st.session_state['import_success_msg'] = f"✅ {imp_msg}"
|
|
st.session_state.pop('preview_data', None)
|
|
st.rerun()
|
|
else:
|
|
st.error(imp_msg)
|
|
|
|
with btn_c2:
|
|
if st.button("❌ Cancelar", use_container_width=True):
|
|
st.session_state.pop('preview_data', None)
|
|
st.rerun()
|
|
else:
|
|
if not st.session_state.get('import_success_msg'):
|
|
st.info("👈 Insira os parâmetros ao lado e clique em **Buscar no Google Maps** para visualizar e escolher os leads.")
|