| import streamlit as st |
| import mysql.connector |
| import pandas as pd |
| import bcrypt |
| import re |
| import pytz |
| from datetime import datetime |
|
|
| |
| st.set_page_config(page_title="Sistema de Consulta de Alunos", layout="wide") |
| st.markdown(""" |
| <style> |
| /* Esconde o menu sanduíche e a barra superior do Streamlit */ |
| #MainMenu {visibility: hidden;} |
| header {visibility: hidden;} |
| footer {visibility: hidden;} |
| |
| /* Ajuste para diminuir o espaço em branco no topo após esconder o header */ |
| .block-container { |
| padding-top: 1rem; |
| padding-bottom: 0rem; |
| } |
| </style> |
| """, unsafe_allow_html=True) |
|
|
| |
| 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 |
| ) |
|
|
| |
| 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') |
|
|
| |
| def obter_hora_brasilia(): |
| |
| fuso_br = pytz.timezone('America/Sao_Paulo') |
| |
| return datetime.now(fuso_br) |
| |
| |
| hide_st_style = """ |
| <style> |
| #MainMenu {visibility: hidden;} |
| header {visibility: hidden;} |
| footer {visibility: hidden;} |
| .stDeployButton {display:none;} |
| </style> |
| """ |
| st.markdown(hide_st_style, unsafe_allow_html=True) |
|
|
| |
| if 'logado' not in st.session_state: |
| st.session_state.logado = False |
| st.session_state.perfil = None |
| st.session_state.nome_usuario = "" |
|
|
| |
| 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'] |
|
|
| |
| try: |
| |
| 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() |
| |
| |
| sql_log = """ |
| INSERT INTO app_logs_acesso (usuario_id, nome_usuario, email, data_acesso) |
| VALUES (%s, %s, %s, %s) |
| """ |
| |
| 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}") |
| |
| st.rerun() |
| |
| else: |
| st.error("Credenciais inválidas ou conta desativada.") |
| except Exception as e: |
| st.error(f"Erro de conexão: {e}") |
| |
| |
| else: |
| |
| st.sidebar.title(f"👤 {st.session_state.nome_usuario}") |
| |
| |
| perfil_usuario = str(st.session_state.perfil).lower().strip() |
| st.sidebar.write(f"Perfil: **{perfil_usuario.upper()}**") |
| st.sidebar.markdown("---") |
| |
| |
| opcoes_menu = ["Consultar Histórico", "Relatório de Aprovação", "Relatórios de Retenção", "Alunos sem Acesso", "Equipe de Apoio"] |
| |
| |
| 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() |
|
|
| |
| |
| |
| 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']})" |
| |
| |
| 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) |
| |
| |
| 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}") |
|
|
| |
| |
| |
| 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() |
|
|
| |
| 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) |
|
|
| |
| 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) |
|
|
| |
| 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")) |
|
|
| |
| apenas_aprovados = st.checkbox("Exibir apenas alunos aprovados (Completou Aula 15)") |
|
|
| if st.button("Gerar Relatório de Aprovação"): |
| |
| 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: |
| |
| 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" |
| ) |
|
|
| |
| 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) |
|
|
| |
| 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}") |
| |
| |
| |
| |
| 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) |
| |
| |
| |
| col_dl1, col_dl2 = st.columns(2) |
| |
| |
| 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 |
| ) |
| |
| |
| 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}") |
|
|
| |
| |
| |
| 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() |
| |
| |
| 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) |
| ) |
| |
| |
| 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() |
| |
| except Exception as e: |
| st.error(f"Erro: {e}") |
| |
| |
| try: |
| conn = get_connection() |
| |
| 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: |
| |
| df_users['ativo'] = df_users['ativo'].map({1: 'Sim', 0: 'Não'}) |
|
|
| |
| |
| 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" |
| ) |
|
|
| |
| 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}") |
| |
| |
| |
| |
| elif menu == "Alunos sem Acesso": |
| st.title("🚫 Alunos sem Acesso (Semestre Atual)") |
| |
| |
| hoje = datetime.now() |
| semestre_atual = f"{hoje.year}.{1 if hoje.month <= 6 else 2}" |
| |
| try: |
| conn = get_connection() |
| |
| |
| 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) |
|
|
| |
| 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) |
| |
| 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"): |
| |
| filtro_sql = "" |
| if curso_selecionado != "Todos": |
| filtro_sql += f" AND nome_curso = '{curso_selecionado}'" |
| |
| if turma_selecionada != "Todas": |
| |
| 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) |
|
|
| |
| col_dl1, col_dl2 = st.columns(2) |
| |
| |
| 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 |
| ) |
| |
| |
| 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}") |
| |
| |
| |
| |
| elif menu == "Logs do Sistema" and perfil_usuario == 'admin': |
| st.title("📜 Auditoria e Logs do Sistema") |
| |
| |
| 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: |
| |
| 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) |
| |
| |
| 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}") |
| |
| |
| |
| |
| 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() |
| |
| |
| 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: |
| |
| 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}'" |
| |
| |
| 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.") |
| |
| |
| st.dataframe(df_equipe, use_container_width=True, hide_index=True) |
| |
| |
| 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}") |
| |
| |