import streamlit as st import warnings warnings.filterwarnings("ignore") from config import get_css_styles, get_settings, get_translation from data_handler import load_preset_data, load_uploaded_data, data_health_check from analytics import get_material_stats, detect_outliers, create_total_production_chart, create_materials_trend_chart, create_shift_trend_chart from ai_engine import init_ai_model from typing import Dict from datetime import datetime from utils import init_session_state st.set_page_config( page_title="Production Monitor with AI Insights | Nilsen Service & Consulting", page_icon="🏭", layout="wide", initial_sidebar_state="expanded" ) def render_welcome_screen(t: Dict): st.markdown(f'
{t["welcome_title"]}
', unsafe_allow_html=True) col1, col2 = st.columns(2) with col1: st.markdown(f"### {t['welcome_quick_start']}") st.markdown(t['welcome_steps']) with col2: st.markdown(f"### {t['welcome_features']}") st.markdown(t['welcome_features_list']) st.info(t['welcome_ready']) def main(): st.markdown(get_css_styles(), unsafe_allow_html=True) lang = st.sidebar.selectbox("Language", ["English", "Norsk"], index=1) t = get_translation(lang) st.markdown(f"""
{t['page_title']}
{t['page_subtitle']}
""", unsafe_allow_html=True) init_session_state() model = init_ai_model() settings = get_settings() with st.sidebar: st.markdown(f"### {t['sidebar_data_source']}") uploaded_file = st.file_uploader(t['sidebar_upload'], type=['csv']) st.markdown("---") st.markdown(f"### {t['sidebar_quick_load']}") col1, col2 = st.columns(2) with col1: if st.button("2024 Data", type="primary", key="load_2024"): st.session_state.load_preset = "2024" with col2: if st.button("2025 Data", type="primary", key="load_2025"): st.session_state.load_preset = "2025" st.markdown("---") st.markdown(t['sidebar_format_hint']) if model: st.success(f"{t['ai_ready']} ({settings.environment})") else: st.warning(t['ai_unavailable']) st.info(t['ai_config_hint']) df = st.session_state.current_df stats = st.session_state.current_stats if uploaded_file: try: df = load_uploaded_data(uploaded_file) stats = get_material_stats(df) st.session_state.current_df = df st.session_state.current_stats = stats st.success(t['data_uploaded']) except Exception as e: st.error(f"Error loading uploaded file: {str(e)}") elif 'load_preset' in st.session_state: year = st.session_state.load_preset try: with st.spinner(f"Loading {year} data..."): df = load_preset_data(year) if df is not None: stats = get_material_stats(df) st.session_state.current_df = df st.session_state.current_stats = stats st.success(f"{year} {t['data_loaded']}") except Exception as e: st.error(f"Error loading {year} data: {str(e)}") finally: del st.session_state.load_preset if df is not None and stats is not None: health = data_health_check(df) with st.expander(t['data_health']): cols = st.columns(4) for i, (key, value) in enumerate(health.items()): with cols[i]: st.metric(key, value) st.markdown(f'
{t["section_material_overview"]}
', unsafe_allow_html=True) materials = [k for k in stats.keys() if k != '_total_'] cols = st.columns(4) for i, material in enumerate(materials[:3]): info = stats[material] with cols[i]: st.metric( label=material.replace('_', ' ').title(), value=f"{info['total']:,.0f} kg", delta=f"{info['percentage']:.1f}% of total" ) st.caption(f"{t['metric_daily_avg']}: {info['daily_avg']:,.0f} kg") if len(materials) >= 3: total_info = stats['_total_'] with cols[3]: st.metric( label=t['metric_total'], value=f"{total_info['total']:,.0f} kg", delta="100% of total" ) st.caption(f"{t['metric_daily_avg']}: {total_info['daily_avg']:,.0f} kg") st.markdown(f'
{t["section_production_trends"]}
', unsafe_allow_html=True) col1, col2 = st.columns([3, 1]) with col2: time_view = st.selectbox(t['time_period'], ["daily", "weekly", "monthly"], key="time_view_select") with col1: with st.container(): st.markdown('
', unsafe_allow_html=True) total_chart = create_total_production_chart(df, time_view, lang) st.plotly_chart(total_chart, use_container_width=True) st.markdown('
', unsafe_allow_html=True) st.markdown(f'
{t["section_materials_analysis"]}
', unsafe_allow_html=True) col1, col2 = st.columns([3, 1]) with col2: selected_materials = st.multiselect( t['select_materials'], options=materials, default=materials, key="materials_select" ) with col1: if selected_materials: with st.container(): st.markdown('
', unsafe_allow_html=True) materials_chart = create_materials_trend_chart(df, time_view, selected_materials, lang) st.plotly_chart(materials_chart, use_container_width=True) st.markdown('
', unsafe_allow_html=True) if 'shift' in df.columns: st.markdown(f'
{t["section_shift_analysis"]}
', unsafe_allow_html=True) with st.container(): st.markdown('
', unsafe_allow_html=True) shift_chart = create_shift_trend_chart(df, time_view, lang) st.plotly_chart(shift_chart, use_container_width=True) st.markdown('
', unsafe_allow_html=True) outliers = detect_outliers(df) st.markdown(f'
{t["section_quality_check"]}
', unsafe_allow_html=True) cols = st.columns(len(outliers)) for i, (material, info) in enumerate(outliers.items()): with cols[i]: if info['count'] > 0: dates_str = ", ".join(info['dates']) st.markdown(f'''
{material.title()}
{info["count"]} {t['quality_outliers']}
{t['quality_normal_range']}: {info["range"]}
Dates: {dates_str}
''', unsafe_allow_html=True) else: st.markdown(f'
{material.title()}
{t["quality_normal"]}
', unsafe_allow_html=True) st.markdown(f'
{t["section_export"]}
', unsafe_allow_html=True) col1, col2, col3 = st.columns(3) with col1: if st.button(t['btn_generate_pdf'], key="generate_pdf_btn", type="primary"): try: with st.spinner(t['pdf_generating']): from pdf_generator import create_enhanced_pdf_report st.session_state.pdf_buffer = create_enhanced_pdf_report(df, stats, outliers, model, lang) st.session_state.export_ready = True st.success(t['pdf_success']) except Exception as e: st.error(f"{t['pdf_failed']}: {str(e)}") st.session_state.export_ready = False if st.session_state.export_ready and st.session_state.pdf_buffer: st.download_button( label=t['btn_download_pdf'], data=st.session_state.pdf_buffer, file_name=f"production_report_{datetime.now().strftime('%Y%m%d_%H%M')}.pdf", mime="application/pdf", key="download_pdf_btn" ) with col2: if st.button(t['btn_generate_csv'], key="generate_csv_btn", type="primary"): try: from pdf_generator import create_csv_export st.session_state.csv_data = create_csv_export(df, stats) st.success(t['csv_success']) except Exception as e: st.error(f"{t['csv_failed']}: {str(e)}") if st.session_state.csv_data is not None: csv_string = st.session_state.csv_data.to_csv(index=False) st.download_button( label=t['btn_download_csv'], data=csv_string, file_name=f"production_summary_{datetime.now().strftime('%Y%m%d_%H%M')}.csv", mime="text/csv", key="download_csv_btn" ) with col3: csv_string = df.to_csv(index=False) st.download_button( label=t['btn_download_raw'], data=csv_string, file_name=f"raw_production_data_{datetime.now().strftime('%Y%m%d_%H%M')}.csv", mime="text/csv", key="download_raw_btn" ) if model: st.markdown(f'
{t["section_ai_insights"]}
', unsafe_allow_html=True) quick_questions = [t['ai_quick_q1'], t['ai_quick_q2'], t['ai_quick_q3']] cols = st.columns(len(quick_questions)) for i, q in enumerate(quick_questions): with cols[i]: if st.button(q, key=f"ai_q_{i}"): from ai_engine import query_ai with st.spinner(t['ai_analyzing']): answer = query_ai(model, stats, q, df, lang) st.info(answer) custom_question = st.text_input( t['ai_ask_label'], placeholder=t['ai_custom_placeholder'], key="custom_ai_question" ) if custom_question and st.button(t['ai_ask_btn'], key="ask_ai_btn"): from ai_engine import query_ai with st.spinner(t['ai_analyzing']): answer = query_ai(model, stats, custom_question, df, lang) st.success(f"**Q:** {custom_question}") st.write(f"**A:** {answer}") else: st.markdown(f'
{t["section_ai_config"]}
', unsafe_allow_html=True) st.info(t['ai_config_info']) else: render_welcome_screen(t) if __name__ == "__main__": main()