import streamlit as st import sys import os import pandas as pd import seaborn as sns import matplotlib.pyplot as plt from datetime import datetime, timedelta import plotly.express as px import plotly.graph_objects as go # Adiciona o diretório pai ao path para importar módulos sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) # Importa as funções do banco de dados from db.db_resp_usuario import obter_todas_respostas # Configuração da página st.set_page_config( page_title="Dashboard - Pesquisa de Satisfação", page_icon="📊", layout="wide" ) st.title("📊 Painel de Acompanhamento - Pesquisa de Satisfação do Serviço de Limpeza") # Função para carregar dados @st.cache_data(ttl=300) # Cache por 5 minutos def carregar_dados(): try: respostas = obter_todas_respostas() if respostas: colunas = ['ID', 'Setor', 'Material Faltando', 'Qual Material', 'Qualidade Serviço', 'Mensagem', 'Data Registro'] df = pd.DataFrame(respostas, columns=colunas) # Converte boolean para texto df['Material Faltando'] = df['Material Faltando'].map({True: 'Sim', False: 'Não'}) # Converte data para datetime df['Data Registro'] = pd.to_datetime(df['Data Registro']) return df else: return pd.DataFrame() except Exception as e: st.error(f"❌ Erro ao carregar dados: {str(e)}") return pd.DataFrame() # Carrega os dados df = carregar_dados() # Botão para atualizar dados if st.button("🔄 Atualizar Dados"): st.cache_data.clear() st.rerun() if df.empty: st.warning("📭 Nenhuma resposta encontrada no banco de dados.") st.info("💡 Execute o formulário em `sentimentos/app.py` para gerar dados.") else: # Informações gerais st.markdown("---") st.subheader("📈 Métricas Gerais") # Métricas principais col1, col2, col3, col4 = st.columns(4) with col1: total_respostas = len(df) st.metric("🔢 Total de Respostas", total_respostas) with col2: material_faltando = len(df[df['Material Faltando'] == 'Sim']) percentual_falta = (material_faltando / total_respostas) * 100 if total_respostas > 0 else 0 st.metric("🧴 Material Faltando", f"{material_faltando} ({percentual_falta:.1f}%)") with col3: satisfacao_boa = len(df[df['Qualidade Serviço'].isin(['Muito Bom', 'Bom'])]) percentual_satisfacao = (satisfacao_boa / total_respostas) * 100 if total_respostas > 0 else 0 st.metric("⭐ Satisfação Positiva", f"{satisfacao_boa} ({percentual_satisfacao:.1f}%)") with col4: # Última resposta ultima_resposta = df['Data Registro'].max() dias_atras = (datetime.now() - ultima_resposta).days st.metric("📅 Última Resposta", f"Há {dias_atras} dias") # Gráficos - Linha 1 st.markdown("---") st.subheader("📊 Análise por Setor") col1, col2 = st.columns(2) with col1: # Gráfico de respostas por setor st.markdown("#### 🏢 Respostas por Setor") setor_counts = df['Setor'].value_counts() fig_setor = px.pie( values=setor_counts.values, names=setor_counts.index, title="Distribuição de Respostas por Setor" ) st.plotly_chart(fig_setor, use_container_width=True) with col2: # Gráfico de qualidade do serviço st.markdown("#### ⭐ Avaliação da Qualidade") qualidade_counts = df['Qualidade Serviço'].value_counts() fig_qualidade = px.bar( x=qualidade_counts.index, y=qualidade_counts.values, title="Avaliação da Qualidade do Serviço", color=qualidade_counts.values, color_continuous_scale="RdYlGn" ) fig_qualidade.update_layout(showlegend=False) st.plotly_chart(fig_qualidade, use_container_width=True) # Gráficos - Linha 2 st.markdown("---") st.subheader("🧽 Análise de Materiais") col1, col2 = st.columns(2) with col1: # Material faltando por setor st.markdown("#### 🏢 Material Faltando por Setor") material_setor = pd.crosstab(df['Setor'], df['Material Faltando']) fig_material_setor = px.bar( material_setor, title="Material Faltando por Setor", color_discrete_map={'Sim': '#ff6b6b', 'Não': '#51cf66'} ) st.plotly_chart(fig_material_setor, use_container_width=True) with col2: # Tipos de material em falta st.markdown("#### 🧴 Tipos de Material em Falta") material_falta = df[df['Material Faltando'] == 'Sim']['Qual Material'].value_counts() if not material_falta.empty: fig_tipos = px.bar( x=material_falta.values, y=material_falta.index, orientation='h', title="Materiais Mais Solicitados", color=material_falta.values, color_continuous_scale="Reds" ) fig_tipos.update_layout(showlegend=False) st.plotly_chart(fig_tipos, use_container_width=True) else: st.info("Nenhum material em falta reportado.") # Análise temporal st.markdown("---") st.subheader("📅 Análise Temporal") # Respostas ao longo do tempo df['Data'] = df['Data Registro'].dt.date respostas_diarias = df.groupby('Data').size().reset_index(name='Quantidade') fig_temporal = px.line( respostas_diarias, x='Data', y='Quantidade', title="Respostas ao Longo do Tempo", markers=True ) st.plotly_chart(fig_temporal, use_container_width=True) # Heatmap de qualidade por setor usando seaborn st.markdown("---") st.subheader("🔥 Heatmap - Qualidade por Setor") # Prepara dados para heatmap qualidade_setor = pd.crosstab(df['Setor'], df['Qualidade Serviço']) # Cria figura matplotlib para seaborn fig_heatmap, ax = plt.subplots(figsize=(10, 6)) sns.heatmap( qualidade_setor, annot=True, fmt='d', cmap='RdYlGn', ax=ax, cbar_kws={'label': 'Número de Respostas'} ) ax.set_title('Heatmap: Qualidade do Serviço por Setor') plt.xticks(rotation=45) plt.tight_layout() st.pyplot(fig_heatmap) # Tabela detalhada st.markdown("---") st.subheader("📋 Dados Detalhados") # Filtros col1, col2, col3 = st.columns(3) with col1: setores_selecionados = st.multiselect( "Filtrar por Setor:", options=df['Setor'].unique(), default=df['Setor'].unique() ) with col2: qualidade_selecionada = st.multiselect( "Filtrar por Qualidade:", options=df['Qualidade Serviço'].unique(), default=df['Qualidade Serviço'].unique() ) with col3: material_selecionado = st.selectbox( "Filtrar Material Faltando:", options=['Todos', 'Sim', 'Não'], index=0 ) # Aplica filtros df_filtrado = df[ (df['Setor'].isin(setores_selecionados)) & (df['Qualidade Serviço'].isin(qualidade_selecionada)) ] if material_selecionado != 'Todos': df_filtrado = df_filtrado[df_filtrado['Material Faltando'] == material_selecionado] # Mostra tabela filtrada st.dataframe( df_filtrado[['Setor', 'Material Faltando', 'Qual Material', 'Qualidade Serviço', 'Mensagem', 'Data Registro']], use_container_width=True ) # Estatísticas dos dados filtrados if not df_filtrado.empty: st.markdown("#### 📊 Estatísticas dos Dados Filtrados") col1, col2, col3 = st.columns(3) with col1: st.metric("Respostas Filtradas", len(df_filtrado)) with col2: media_qualidade = df_filtrado['Qualidade Serviço'].mode()[0] if not df_filtrado.empty else "N/A" st.metric("Avaliação Mais Comum", media_qualidade) with col3: material_falta_filtrado = len(df_filtrado[df_filtrado['Material Faltando'] == 'Sim']) st.metric("Material Faltando", material_falta_filtrado) # Rodapé st.markdown("---") st.markdown("📊 **Dashboard de Pesquisa de Satisfação** | Atualizado automaticamente a cada 5 minutos") st.markdown("💡 *Dica: Use os filtros para análises mais específicas*")