import streamlit as st
import mysql.connector
import pandas as pd
import bcrypt
import re
import pytz
from datetime import datetime
# --- CONFIGURAÇÕES DA PÁGINA ---
st.set_page_config(page_title="Sistema de Consulta de Alunos", layout="wide")
st.markdown("""
""", unsafe_allow_html=True)
# --- CONEXÃO COM O BANCO ---
def get_connection():
return mysql.connector.connect(
user=st.secrets["DB_USER"],
password=st.secrets["DB_PASS"],
host=st.secrets["DB_HOST"],
port=st.secrets["DB_PORT"],
database=st.secrets["DB_NAME"],
ssl_ca="ca.pem",
use_pure=True
)
# --- FUNÇÕES DE SEGURANÇA ---
def verificar_senha(senha_plana, senha_hash):
return bcrypt.checkpw(senha_plana.encode('utf-8'), senha_hash.encode('utf-8'))
def gerar_hash(senha):
return bcrypt.hashpw(senha.encode('utf-8'), bcrypt.gensalt()).decode('utf-8')
# --- FUNÇÕES DA APLICAÇÃO ---
def obter_hora_brasilia():
# Define o fuso horário de Brasília explicitamente
fuso_br = pytz.timezone('America/Sao_Paulo')
# Pega a hora atual nesse fuso
return datetime.now(fuso_br)
# --- REMOVER BARRA SUPERIOR E MENU DO STREAMLIT ---
hide_st_style = """
"""
st.markdown(hide_st_style, unsafe_allow_html=True)
# --- ESTADO DA SESSÃO ---
if 'logado' not in st.session_state:
st.session_state.logado = False
st.session_state.perfil = None
st.session_state.nome_usuario = ""
# --- TELA DE LOGIN ---
if not st.session_state.logado:
st.title("🔐 Acesso ao Sistema")
with st.form("login_form"):
email = st.text_input("E-mail")
senha = st.text_input("Senha", type="password")
btn_login = st.form_submit_button("Entrar")
if btn_login:
try:
conn = get_connection()
cursor = conn.cursor(dictionary=True)
cursor.execute("SELECT id, nome, senha_hash, perfil, ativo FROM app_usuarios WHERE email = %s", (email,))
user = cursor.fetchone()
conn.close()
if user and user['ativo'] and verificar_senha(senha, user['senha_hash']):
st.session_state.logado = True
st.session_state.perfil = user['perfil']
st.session_state.nome_usuario = user['nome']
# --- REGISTRO DE LOG DE ACESSO ---
try:
# 1. Calcula a hora de Brasília usando a lógica do pytz
agora_br = obter_hora_brasilia()
data_acesso_str = agora_br.strftime('%Y-%m-%d %H:%M:%S')
conn_log = get_connection()
cursor_log = conn_log.cursor()
# 2. Insere explicitamente a data calculada
sql_log = """
INSERT INTO app_logs_acesso (usuario_id, nome_usuario, email, data_acesso)
VALUES (%s, %s, %s, %s)
"""
# Passamos o user['id'] que agora buscamos no SELECT acima
valores_log = (user['id'], user['nome'], email, data_acesso_str)
cursor_log.execute(sql_log, valores_log)
conn_log.commit()
conn_log.close()
except Exception as e:
print(f"Erro ao salvar log de acesso: {e}") # Verifique isso nos Logs do Hugging Face
st.rerun()
else:
st.error("Credenciais inválidas ou conta desativada.")
except Exception as e:
st.error(f"Erro de conexão: {e}")
# --- ÁREA LOGADA ---
else:
# Sidebar - Perfil e Navegação
st.sidebar.title(f"👤 {st.session_state.nome_usuario}")
# Normalizamos o perfil para evitar erros de Digitação/Maiúsculas
perfil_usuario = str(st.session_state.perfil).lower().strip()
st.sidebar.write(f"Perfil: **{perfil_usuario.upper()}**")
st.sidebar.markdown("---")
# OPÇÕES PARA TODOS OS USUÁRIOS (Consulta e Admin)
opcoes_menu = ["Consultar Histórico", "Relatório de Aprovação", "Relatórios de Retenção", "Alunos sem Acesso", "Equipe de Apoio"]
# OPÇÃO EXCLUSIVA PARA ADMIN
if perfil_usuario == 'admin':
opcoes_menu.append("Gerenciar Usuários")
opcoes_menu.append("Logs do Sistema")
menu = st.sidebar.radio("Navegação", opcoes_menu)
st.sidebar.markdown("---")
if st.sidebar.button("Sair"):
st.session_state.logado = False
st.rerun()
#######################################################
# --- MÓDULO 1: CONSULTA DE HISTÓRICO ---
#######################################################
if menu == "Consultar Histórico":
st.title("🔍 Consulta de Histórico de Alunos")
busca = st.text_input("Pesquisar por Nome, Sobrenome ou E-mail")
if busca:
try:
conn = get_connection()
termo = f"%{busca}%"
query = """
SELECT
nome, sobrenome, email, ultimo_acesso,
cidade, pais, celular,
nome_curso, semestre_referencia, papel, turmas, data_inicial
FROM portal_alunos_flat
WHERE nome LIKE %s OR sobrenome LIKE %s OR email LIKE %s
ORDER BY nome ASC, semestre_referencia ASC, nome_curso ASC
"""
df = pd.read_sql(query, conn, params=(termo, termo, termo))
conn.close()
if not df.empty:
colunas_aluno = ['nome', 'sobrenome', 'email', 'ultimo_acesso', 'cidade', 'pais', 'celular']
alunos = df[colunas_aluno].drop_duplicates()
for _, aluno in alunos.iterrows():
label_expander = f"👤 {aluno['nome']} {aluno['sobrenome']} ({aluno['email']})"
# --- TRATAMENTO DE CAMPOS VAZIOS ---
celular_valor = str(aluno['celular']).strip() if aluno['celular'] and str(aluno['celular']).lower() != 'nan' else ""
celular_display = celular_valor if celular_valor else "Não cadastrado"
ultimo_acesso = str(aluno['ultimo_acesso']) if aluno['ultimo_acesso'] else "Nunca"
localizacao = f"{aluno['cidade']} / {aluno['pais']}" if aluno['cidade'] else "Não informada"
with st.expander(label_expander):
col1, col2, col3, col4 = st.columns(4)
col1.metric(label="📅 Último Logon", value=ultimo_acesso)
col2.metric(label="📍 Localização", value=localizacao)
col3.metric(label="📱 Celular", value=celular_display)
# Opcional: Link para WhatsApp apenas se houver celular
if celular_valor:
f_tel = "".join(filter(str.isdigit, celular_valor))
if f_tel:
col4.markdown(f"[💬 WhatsApp](https://wa.me/{f_tel})")
else:
col4.write("🚫 Número inválido")
else:
col4.write("━")
st.write("---")
hist = df[df['email'] == aluno['email']][['semestre_referencia', 'nome_curso', 'papel', 'turmas', 'data_inicial']]
hist = hist.sort_values(by=['semestre_referencia', 'nome_curso'])
hist.columns = ['Semestre', 'Curso', 'Papel', 'Turmas', 'Início']
st.dataframe(hist, use_container_width=True, hide_index=True)
else:
st.warning("Nenhum aluno encontrado.")
except Exception as e:
st.error(f"Erro ao consultar: {e}")
#######################################################
# --- MÓDULO 2: RELATÓRIO DE APROVAÇÃO ---
#######################################################
elif menu == "Relatório de Aprovação":
st.title("🎓 Relatório de Aprovação")
st.write("Consulta de progresso e aprovação dos alunos por ciclo letivo.")
try:
conn = get_connection()
# --- FILTRO 1: SEMESTRE DE REFERÊNCIA ---
query_semestres = """
SELECT DISTINCT semestre_referencia
FROM portal_alunos_flat
WHERE semestre_referencia IS NOT NULL AND semestre_referencia != ''
ORDER BY semestre_referencia DESC
"""
df_semestres = pd.read_sql(query_semestres, conn)
lista_semestres = df_semestres['semestre_referencia'].tolist()
col_sem, col_cur, col_tur = st.columns(3)
with col_sem:
semestre_sel = st.selectbox("Selecione o Semestre:", lista_semestres)
# --- FILTRO 2: CURSO (Dependente do Semestre) ---
query_cursos = f"""
SELECT DISTINCT nome_curso
FROM portal_alunos_flat
WHERE semestre_referencia = '{semestre_sel}'
ORDER BY nome_curso
"""
df_cursos = pd.read_sql(query_cursos, conn)
lista_cursos = ["Todos"] + df_cursos['nome_curso'].tolist()
with col_cur:
curso_sel = st.selectbox("Filtrar por Curso:", lista_cursos)
# --- FILTRO 3: TURMA (Dependente do Curso) ---
lista_turmas = ["Todas"]
if curso_sel != "Todos":
query_turmas = f"""
SELECT DISTINCT turmas
FROM portal_alunos_flat
WHERE semestre_referencia = '{semestre_sel}'
AND nome_curso = '{curso_sel}'
AND turmas IS NOT NULL AND turmas != ''
ORDER BY turmas
"""
df_turmas = pd.read_sql(query_turmas, conn)
lista_turmas = ["Todas"] + sorted(df_turmas['turmas'].unique().tolist())
with col_tur:
turma_sel = st.selectbox("Filtrar por Turma:", lista_turmas, disabled=(curso_sel == "Todos"))
# --- FILTRO CONTROLE: APENAS APROVADOS ---
apenas_aprovados = st.checkbox("Exibir apenas alunos aprovados (Completou Aula 15)")
if st.button("Gerar Relatório de Aprovação"):
# Construção dinâmica da query baseada nos filtros selecionados
condicoes = [f"semestre_referencia = '{semestre_sel}'", "papel = 'Estudante'"]
if curso_sel != "Todos":
condicoes.append(f"nome_curso = '{curso_sel}'")
if turma_sel != "Todas":
condicoes.append(f"turmas LIKE '%%{turma_sel}%%'")
if apenas_aprovados:
condicoes.append("completou_aula_15 = 'Sim'")
where_clause = " AND ".join(condicoes)
query_relatorio = f"""
SELECT
nome,
sobrenome,
email,
celular,
nome_curso,
turmas,
completou_aula_15 as aprovado,
data_conclusao_aula_15
FROM portal_alunos_flat
WHERE {where_clause}
ORDER BY nome_curso ASC, turmas ASC, nome ASC
"""
df_aprovacao = pd.read_sql(query_relatorio, conn)
if not df_aprovacao.empty:
# Tratar a data "1969-12-31" para uma exibição amigável no relatório
df_aprovacao['data_conclusao_aula_15'] = df_aprovacao['data_conclusao_aula_15'].apply(
lambda x: x.strftime('%d/%m/%Y') if pd.notnull(x) and str(x) != '1969-12-31' else "Não concluído"
)
# Renomear colunas para exibição na tela
df_exibicao = df_aprovacao.copy()
df_exibicao.columns = ['Nome', 'Sobrenome', 'E-mail', 'Telefone', 'Curso', 'Turma', 'Aprovado (Aula 15)', 'Data de Conclusão']
st.success(f"Foram encontrados {len(df_aprovacao)} registros.")
st.dataframe(df_exibicao, use_container_width=True, hide_index=True)
# --- EXPORTAÇÃO EXCEL (.XLSX) ---
import io
output = io.BytesIO()
with pd.ExcelWriter(output, engine='openpyxl') as writer:
df_exibicao.to_excel(writer, index=False, sheet_name='Relatório de Aprovação')
excel_data = output.getvalue()
st.download_button(
label="📊 Exportar Relatório para Excel (.xlsx)",
data=excel_data,
file_name=f"relatorio_aprovacao_{semestre_sel}.xlsx",
mime="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
)
else:
st.warning("Nenhum aluno encontrado para os filtros aplicados.")
conn.close()
except Exception as e:
st.error(f"Erro ao processar relatório de aprovação: {e}")
#######################################################
# --- MÓDULO 3: RELATÓRIO DE RETENÇÃO ---
#######################################################
elif menu == "Relatórios de Retenção":
st.title("📊 Relatório de Retenção: Ciclo IX para X")
st.write("Alunos que cursaram Ciclo IX, mas não constam no Ciclo X do semestre .")
qtd_semestres = st.number_input("Semestres anteriores (excluindo atual):", 1, 10, 2)
hoje = datetime.now()
ano, sem_atual = hoje.year, (1 if hoje.month <= 6 else 2)
lista_semestres = []
t_ano, t_sem = ano, sem_atual
for _ in range(qtd_semestres):
if t_sem == 1: t_ano -= 1; t_sem = 2
else: t_sem = 1
lista_semestres.append(f"{t_ano}.{t_sem}")
st.info(f"Analisando: {', '.join(lista_semestres)}")
if st.button("Gerar Relatório"):
try:
conn = get_connection()
semestres_sql = "', '".join(lista_semestres)
query = f"""
SELECT nome, sobrenome, email, celular, semestre_referencia
FROM portal_alunos_flat
WHERE papel = 'Estudante'
AND nome_curso LIKE '%%Ciclo IX%%'
AND semestre_referencia IN ('{semestres_sql}')
AND email NOT IN (
SELECT DISTINCT email FROM portal_alunos_flat
WHERE nome_curso LIKE '%%Ciclo X%%' AND papel = 'Estudante'
)
ORDER BY semestre_referencia DESC, nome ASC
"""
df_retidos = pd.read_sql(query, conn)
conn.close()
if not df_retidos.empty:
st.success(f"Encontrados {len(df_retidos)} alunos.")
st.dataframe(df_retidos, use_container_width=True, hide_index=True)
#csv = df_retidos.to_csv(index=False).encode('utf-8-sig')
#st.download_button("📥 Baixar CSV", csv, "retidos.csv", "text/csv")
# --- PREPARAÇÃO DOS ARQUIVOS PARA DOWNLOAD ---
col_dl1, col_dl2 = st.columns(2)
# Opção 1: CSV
csv = df_retidos.to_csv(index=False).encode('utf-8-sig')
with col_dl1:
st.download_button(
label="📥 Baixar em CSV",
data=csv,
file_name=f"retidos.csv",
mime="text/csv",
use_container_width=True
)
# Opção 2: EXCEL (XLSX)
import io
output = io.BytesIO()
with pd.ExcelWriter(output, engine='openpyxl') as writer:
df_retidos.to_excel(writer, index=False, sheet_name='Retenção')
excel_data = output.getvalue()
with col_dl2:
st.download_button(
label="📊 Baixar em Excel",
data=excel_data,
file_name=f"retidos.xlsx",
mime="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
use_container_width=True
)
else:
st.warning("Nenhum aluno encontrado.")
except Exception as e:
st.error(f"Erro no processamento: {e}")
#######################################################
# --- MÓDULO 4: GESTÃO DE USUÁRIOS ---
#######################################################
elif menu == "Gerenciar Usuários":
st.title("👥 Gestão de Usuários")
with st.expander("➕ Novo Usuário"):
with st.form("cad_user"):
n_nome = st.text_input("Nome")
n_email = st.text_input("E-mail")
n_senha = st.text_input("Senha", type="password")
n_perfil = st.selectbox("Perfil", ["consulta", "admin"])
if st.form_submit_button("Salvar"):
try:
agora_br = obter_hora_brasilia()
data_operacao = agora_br.strftime('%Y-%m-%d %H:%M:%S')
conn = get_connection()
cursor = conn.cursor()
# Inserção do Usuário
cursor.execute(
"INSERT INTO app_usuarios (nome, email, senha_hash, perfil) VALUES (%s,%s,%s,%s)",
(n_nome, n_email, gerar_hash(n_senha), n_perfil)
)
# Registro de Log
cursor.execute(
"""
INSERT INTO app_logs_operacoes
(nome_executor, operacao, detalhes, data_operacao)
VALUES (%s, %s, %s, %s)
""",
(
st.session_state.nome_usuario,
'CRIACAO_USUARIO',
f"Criou o usuário: {n_email} com perfil {n_perfil}",
data_operacao
)
)
conn.commit()
conn.close()
st.success(f"Usuário cadastrado com sucesso às {agora_br.strftime('%H:%M:%S')}!")
st.rerun() # Atualiza a lista abaixo imediatamente
except Exception as e:
st.error(f"Erro: {e}")
# --- LISTAGEM DE USUÁRIOS COM ÚLTIMO ACESSO E STATUS FORMATADO ---
try:
conn = get_connection()
# Query com JOIN para buscar o último registro de login de cada usuário
query_users = """
SELECT
u.id,
u.nome,
u.email,
u.perfil,
u.ativo,
MAX(l.data_acesso) as ultimo_acesso
FROM app_usuarios u
LEFT JOIN app_logs_acesso l ON u.id = l.usuario_id
GROUP BY u.id
ORDER BY u.nome ASC
"""
df_users = pd.read_sql(query_users, conn)
conn.close()
if not df_users.empty:
# 1. Ajuste do Status Ativo (1 -> Sim, 0 -> Não)
df_users['ativo'] = df_users['ativo'].map({1: 'Sim', 0: 'Não'})
# 2. Formatação da Data de Último Acesso
# Se for Nulo, exibe 'Nunca acessou', senão formata para padrão BR
df_users['ultimo_acesso'] = df_users['ultimo_acesso'].apply(
lambda x: x.strftime('%d/%m/%Y %H:%M') if pd.notnull(x) else "Nunca acessou"
)
# Renomear colunas para o cabeçalho da tabela
df_users.columns = ['ID', 'Nome', 'E-mail', 'Perfil', 'Ativo', 'Último Acesso']
st.write("### Usuários Cadastrados")
st.dataframe(df_users, use_container_width=True, hide_index=True)
else:
st.info("Nenhum usuário cadastrado.")
except Exception as e:
st.error(f"Erro ao listar usuários: {e}")
#######################################################
# --- MÓDULO 5: ALUNOS SEM ACESSO NO SEMESTRE ATUAL ---
#######################################################
elif menu == "Alunos sem Acesso":
st.title("🚫 Alunos sem Acesso (Semestre Atual)")
# Define o semestre atual dinamicamente
hoje = datetime.now()
semestre_atual = f"{hoje.year}.{1 if hoje.month <= 6 else 2}"
try:
conn = get_connection()
# --- FILTRO 1: CURSO ---
query_cursos = f"""
SELECT DISTINCT nome_curso
FROM portal_alunos_flat
WHERE semestre_referencia = '{semestre_atual}'
ORDER BY nome_curso
"""
df_cursos = pd.read_sql(query_cursos, conn)
lista_cursos = ["Todos"] + df_cursos['nome_curso'].tolist()
col1, col2 = st.columns(2)
with col1:
curso_selecionado = st.selectbox("Filtrar por Curso:", lista_cursos)
# --- FILTRO 2: TURMAS (Ajustado para o nome real da coluna) ---
lista_turmas = ["Todas"]
if curso_selecionado != "Todos":
query_turmas = f"""
SELECT DISTINCT turmas
FROM portal_alunos_flat
WHERE semestre_referencia = '{semestre_atual}'
AND nome_curso = '{curso_selecionado}'
AND turmas IS NOT NULL AND turmas != ''
ORDER BY turmas
"""
df_turmas = pd.read_sql(query_turmas, conn)
# Como a coluna é TEXT, limpamos possíveis valores duplicados ou vazios no Python
lista_turmas = ["Todas"] + sorted(df_turmas['turmas'].unique().tolist())
with col2:
turma_selecionada = st.selectbox("Filtrar por Turma:", lista_turmas, disabled=(curso_selecionado == "Todos"))
if st.button("Gerar Lista"):
# Montagem dinâmica dos filtros SQL
filtro_sql = ""
if curso_selecionado != "Todos":
filtro_sql += f" AND nome_curso = '{curso_selecionado}'"
if turma_selecionada != "Todas":
# Usamos LIKE porque a coluna é TEXT e pode conter múltiplas turmas
filtro_sql += f" AND turmas LIKE '%%{turma_selecionada}%%'"
query_sem_acesso = f"""
SELECT nome, sobrenome, email, celular, nome_curso, turmas, ultimo_acesso
FROM portal_alunos_flat
WHERE papel = 'Estudante'
AND semestre_referencia = '{semestre_atual}'
{filtro_sql}
AND (
ultimo_acesso IS NULL
OR ultimo_acesso = ''
OR ultimo_acesso = '0000-00-00 00:00:00'
OR STR_TO_DATE(ultimo_acesso, '%%d/%%m/%%Y') < '{hoje.year}-01-01'
OR ultimo_acesso NOT LIKE '%%{hoje.year}%%'
)
ORDER BY nome_curso ASC, turmas ASC, nome ASC
"""
df_sem_acesso = pd.read_sql(query_sem_acesso, conn)
if not df_sem_acesso.empty:
st.warning(f"Total de {len(df_sem_acesso)} alunos sem acesso em {semestre_atual}.")
st.dataframe(df_sem_acesso, use_container_width=True, hide_index=True)
# --- PREPARAÇÃO DOS ARQUIVOS PARA DOWNLOAD ---
col_dl1, col_dl2 = st.columns(2)
# Opção 1: CSV
csv = df_sem_acesso.to_csv(index=False).encode('utf-8-sig')
with col_dl1:
st.download_button(
label="📥 Baixar em CSV",
data=csv,
file_name=f"sem_acesso_{semestre_atual}.csv",
mime="text/csv",
use_container_width=True
)
# Opção 2: EXCEL (XLSX)
import io
output = io.BytesIO()
with pd.ExcelWriter(output, engine='openpyxl') as writer:
df_sem_acesso.to_excel(writer, index=False, sheet_name='Alunos Sem Acesso')
excel_data = output.getvalue()
with col_dl2:
st.download_button(
label="📊 Baixar em Excel",
data=excel_data,
file_name=f"sem_acesso_{semestre_atual}.xlsx",
mime="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
use_container_width=True
)
else:
st.success("Parabéns! Todos os alunos selecionados já acessaram o sistema.")
conn.close()
except Exception as e:
st.error(f"Erro ao processar relatório: {e}")
#######################################################
# --- MÓDULO 6: AUDITORIA DE LOGS (APENAS ADMIN) ---
#######################################################
elif menu == "Logs do Sistema" and perfil_usuario == 'admin':
st.title("📜 Auditoria e Logs do Sistema")
# Seletor de Tipo de Log
tipo_log = st.selectbox("Selecione o tipo de registro:",
["Acessos ao Sistema", "Operações de Usuários"])
try:
conn = get_connection()
if tipo_log == "Acessos ao Sistema":
st.subheader("Histórico de Logins")
query = "SELECT nome_usuario, email, data_acesso FROM app_logs_acesso ORDER BY data_acesso DESC"
df_logs = pd.read_sql(query, conn)
else:
st.subheader("Histórico de Alterações Administrativas")
query = "SELECT nome_executor, operacao, detalhes, data_operacao FROM app_logs_operacoes ORDER BY data_operacao DESC"
df_logs = pd.read_sql(query, conn)
conn.close()
if not df_logs.empty:
# Formatação amigável das datas no Pandas antes de exibir
col_data = 'data_acesso' if tipo_log == "Acessos ao Sistema" else 'data_operacao'
df_logs[col_data] = pd.to_datetime(df_logs[col_data]).dt.strftime('%d/%m/%Y %H:%M:%S')
st.dataframe(df_logs, use_container_width=True, hide_index=True)
# Botão para exportar os logs
csv = df_logs.to_csv(index=False).encode('utf-8-sig')
st.download_button(f"📥 Exportar {tipo_log}", csv, f"logs_{tipo_log.lower()}.csv", "text/csv")
else:
st.info("Nenhum registro encontrado nesta categoria.")
except Exception as e:
st.error(f"Erro ao carregar logs: {e}")
#######################################################
# --- MÓDULO 7: CONSULTA DE EQUIPE DE APOIO ---
#######################################################
elif menu == "Equipe de Apoio":
st.title("👥 Consulta de Equipe de Apoio")
st.write("Visualize Professores, Tutores e Coordenadores vinculados aos cursos.")
try:
conn = get_connection()
# 1. Buscar Semestres disponíveis para o primeiro filtro
query_semestres = "SELECT DISTINCT semestre_referencia FROM portal_alunos_flat ORDER BY semestre_referencia DESC"
df_semestres = pd.read_sql(query_semestres, conn)
lista_semestres = df_semestres['semestre_referencia'].tolist()
semestre_sel = st.selectbox("Selecione o Semestre:", lista_semestres)
if semestre_sel:
# 2. Buscar Cursos do semestre selecionado para o segundo filtro
query_cursos = f"""
SELECT DISTINCT nome_curso
FROM portal_alunos_flat
WHERE semestre_referencia = '{semestre_sel}'
ORDER BY nome_curso
"""
df_cursos = pd.read_sql(query_cursos, conn)
lista_cursos = ["Todos"] + df_cursos['nome_curso'].tolist()
curso_sel = st.selectbox("Selecione o Curso:", lista_cursos)
if st.button("Consultar Equipe"):
filtro_curso = "" if curso_sel == "Todos" else f"AND nome_curso = '{curso_sel}'"
# 3. Query Principal: Todos os papéis EXCETO Estudante
query_equipe = f"""
SELECT nome, sobrenome, email, celular, papel, nome_curso, turmas
FROM portal_alunos_flat
WHERE semestre_referencia = '{semestre_sel}'
AND papel != 'Estudante'
{filtro_curso}
ORDER BY nome_curso ASC, papel ASC, nome ASC
"""
df_equipe = pd.read_sql(query_equipe, conn)
if not df_equipe.empty:
st.success(f"Encontrados {len(df_equipe)} membros da equipe.")
# Exibição organizada
st.dataframe(df_equipe, use_container_width=True, hide_index=True)
# Exportação
csv = df_equipe.to_csv(index=False).encode('utf-8-sig')
st.download_button("📥 Baixar Lista de Contatos", csv, f"equipe_{semestre_sel}.csv", "text/csv")
else:
st.warning("Nenhum membro de equipe encontrado para os critérios selecionados.")
conn.close()
except Exception as e:
st.error(f"Erro ao consultar equipe: {e}")