entropy25 commited on
Commit
fe7081a
·
verified ·
1 Parent(s): 888b872

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +142 -95
app.py CHANGED
@@ -89,77 +89,117 @@ def load_css():
89
  box-shadow: 0 1px 3px rgba(0,0,0,0.1);
90
  margin-bottom: 1rem;
91
  }}
 
 
 
 
 
 
 
 
92
  .quality-card {{
93
  background: white;
94
  border: 1px solid {DESIGN_SYSTEM['colors']['border']};
95
- border-radius: 8px;
96
- padding: 20px;
97
- min-height: 120px;
98
- box-shadow: 0 1px 3px rgba(0,0,0,0.1);
99
- transition: transform 0.2s ease;
 
 
100
  }}
101
  .quality-card:hover {{
102
  transform: translateY(-2px);
103
- box-shadow: 0 4px 12px rgba(0,0,0,0.15);
104
  }}
105
  .card-warning {{
106
- border-left: 4px solid {DESIGN_SYSTEM['colors']['warning']};
107
  }}
108
  .card-success {{
109
- border-left: 4px solid {DESIGN_SYSTEM['colors']['success']};
110
- }}
111
- .card-header {{
112
- margin-bottom: 12px;
113
  }}
114
- .material-name {{
115
- font-size: 14px;
116
  font-weight: 600;
117
  color: {DESIGN_SYSTEM['colors']['text']};
 
118
  }}
119
  .status-badge {{
120
  display: inline-block;
121
- padding: 4px 12px;
122
- border-radius: 12px;
123
  font-size: 12px;
124
- font-weight: 500;
125
- margin-bottom: 8px;
 
 
126
  }}
127
- .warning-badge {{
128
- background: {DESIGN_SYSTEM['colors']['warning']}20;
129
  color: {DESIGN_SYSTEM['colors']['warning']};
130
  }}
131
- .success-badge {{
132
- background: {DESIGN_SYSTEM['colors']['success']}20;
133
  color: {DESIGN_SYSTEM['colors']['success']};
134
  }}
135
- .range-text {{
136
- font-size: 12px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
137
  color: #6B7280;
138
- margin-bottom: 8px;
 
 
 
 
 
 
 
 
 
 
 
 
 
139
  }}
140
  .dates-section {{
 
 
 
 
141
  font-size: 11px;
142
  color: #9CA3AF;
143
- line-height: 1.4;
144
- }}
145
- .dates-title {{
146
  font-weight: 600;
147
- margin-bottom: 4px;
 
 
148
  }}
149
  .success-center {{
150
  text-align: center;
151
- margin-top: 20px;
152
- }}
153
- .cards-grid {{
154
- display: flex;
155
- flex-wrap: wrap;
156
- gap: 16px;
157
- margin-top: 20px;
158
  }}
159
- .quality-card-container {{
160
- flex: 1;
161
- min-width: 200px;
 
162
  }}
 
163
  .stButton > button {{
164
  background: {DESIGN_SYSTEM['colors']['primary']};
165
  color: white;
@@ -457,17 +497,17 @@ def render_ai_section(df, stats, model):
457
  """Showcase our AI capabilities and technical achievements"""
458
 
459
  if model:
460
- st.markdown('<div class="section-header">🚀 Our AI-Powered Solution</div>', unsafe_allow_html=True)
461
 
462
  # Demonstrate our capabilities
463
- st.markdown("### 🎯 **Nilsen Service & Consulting - Technical Achievements**")
464
  outliers = detect_outliers(df)
465
  with st.spinner("Demonstrating our AI capabilities..."):
466
  ai_summary = generate_ai_summary(model, df, stats, outliers)
467
  st.success(ai_summary)
468
 
469
  # Show our system's intelligence
470
- st.markdown("### 🧠 **Experience Our Advanced Analytics**")
471
  st.markdown("*See how our AI system provides professional insights for your operations:*")
472
 
473
  demo_questions = [
@@ -479,13 +519,13 @@ def render_ai_section(df, stats, model):
479
  cols = st.columns(len(demo_questions))
480
  for i, question in enumerate(demo_questions):
481
  with cols[i]:
482
- if st.button(f"▶️ {question}", key=f"demo_q_{i}"):
483
  with st.spinner("Our AI analyzing..."):
484
  answer = query_ai(model, stats, question, df)
485
  st.info(f"**Nilsen AI Response:** {answer}")
486
 
487
  # Interactive demonstration
488
- st.markdown("### 💼 **Test Our AI Intelligence**")
489
  col1, col2 = st.columns([3, 1])
490
 
491
  with col1:
@@ -493,8 +533,8 @@ def render_ai_section(df, stats, model):
493
  placeholder="e.g., 'How can your system improve our operational efficiency?'",
494
  key="demo_question")
495
  with col2:
496
- st.markdown("<br>", unsafe_allow_html=True) # Add spacing
497
- if st.button("🚀 **See Our AI in Action**", key="demo_btn", type="primary"):
498
  if custom_question:
499
  with st.spinner("Nilsen AI processing..."):
500
  answer = query_ai(model, stats, custom_question, df)
@@ -507,21 +547,20 @@ def render_ai_section(df, stats, model):
507
  st.markdown("---")
508
  st.markdown("""
509
  <div style="background: linear-gradient(135deg, #1E40AF15, #05966925); padding: 1rem; border-radius: 8px; border: 1px solid #1E40AF;">
510
- <h4>🏆 Why Choose Nilsen Service & Consulting?</h4>
511
  <ul>
512
- <li><strong>Advanced AI Integration:</strong> Cutting-edge analytics for your operations</li>
513
- <li><strong>Professional Reliability:</strong> Enterprise-grade monitoring systems</li>
514
- <li><strong>Proven Results:</strong> Data-driven insights that deliver ROI</li>
515
- <li><strong>Complete Solution:</strong> From data processing to actionable recommendations</li>
516
  </ul>
517
  </div>
518
  """, unsafe_allow_html=True)
519
 
520
  else:
521
- st.markdown('<div class="section-header">🚀 Our AI-Powered Solution</div>', unsafe_allow_html=True)
522
- st.error("⚠️ AI demonstration requires API configuration")
523
- st.info("💡 **Our AI system provides:** Advanced analytics, predictive insights, automated reporting, and intelligent recommendations for production optimization.")
524
-
525
 
526
  def query_ai(model, stats, question, df=None):
527
  if not model:
@@ -805,7 +844,7 @@ def create_csv_export(df, stats):
805
  return summary_df
806
 
807
  def add_export_section(df, stats, outliers, model):
808
- st.markdown('<div class="section-header">📄 Export Reports</div>', unsafe_allow_html=True)
809
  if 'export_ready' not in st.session_state:
810
  st.session_state.export_ready = False
811
  if 'pdf_buffer' not in st.session_state:
@@ -819,13 +858,13 @@ def add_export_section(df, stats, outliers, model):
819
  with st.spinner("Generating PDF with AI analysis..."):
820
  st.session_state.pdf_buffer = create_enhanced_pdf_report(df, stats, outliers, model)
821
  st.session_state.export_ready = True
822
- st.success("PDF report with AI analysis generated successfully!")
823
  except Exception as e:
824
- st.error(f"PDF generation failed: {str(e)}")
825
  st.session_state.export_ready = False
826
  if st.session_state.export_ready and st.session_state.pdf_buffer:
827
  st.download_button(
828
- label="💾 Download PDF Report",
829
  data=st.session_state.pdf_buffer,
830
  file_name=f"production_report_ai_{datetime.now().strftime('%Y%m%d_%H%M')}.pdf",
831
  mime="application/pdf",
@@ -835,13 +874,13 @@ def add_export_section(df, stats, outliers, model):
835
  if st.button("Generate CSV Summary", key="generate_csv_btn", type="primary"):
836
  try:
837
  st.session_state.csv_data = create_csv_export(df, stats)
838
- st.success("CSV summary generated successfully!")
839
  except Exception as e:
840
- st.error(f"CSV generation failed: {str(e)}")
841
  if st.session_state.csv_data is not None:
842
  csv_string = st.session_state.csv_data.to_csv(index=False)
843
  st.download_button(
844
- label="💾 Download CSV Summary",
845
  data=csv_string,
846
  file_name=f"production_summary_{datetime.now().strftime('%Y%m%d_%H%M')}.csv",
847
  mime="text/csv",
@@ -861,7 +900,7 @@ def main():
861
  load_css()
862
  st.markdown("""
863
  <div class="main-header">
864
- <div class="main-title">🏭 Production Monitor with AI Insights</div>
865
  <div class="main-subtitle">Nilsen Service & Consulting AS | Real-time Production Analytics & Recommendations</div>
866
  </div>
867
  """, unsafe_allow_html=True)
@@ -874,16 +913,16 @@ def main():
874
  st.session_state.current_stats = None
875
 
876
  with st.sidebar:
877
- st.markdown("### 📊 Data Source")
878
  uploaded_file = st.file_uploader("Upload Production Data", type=['csv'])
879
  st.markdown("---")
880
- st.markdown("### 📊 Quick Load")
881
  col1, col2 = st.columns(2)
882
  with col1:
883
- if st.button("📊 2024 Data", type="primary", key="load_2024"):
884
  st.session_state.load_preset = "2024"
885
  with col2:
886
- if st.button("📊 2025 Data", type="primary", key="load_2025"):
887
  st.session_state.load_preset = "2025"
888
  st.markdown("---")
889
  st.markdown("""
@@ -894,9 +933,9 @@ def main():
894
  - `shift`: day/night (optional)
895
  """)
896
  if model:
897
- st.success("🤖 AI Assistant Ready")
898
  else:
899
- st.warning("⚠️ AI Assistant Unavailable")
900
 
901
  df = st.session_state.current_df
902
  stats = st.session_state.current_stats
@@ -907,9 +946,9 @@ def main():
907
  stats = get_material_stats(df)
908
  st.session_state.current_df = df
909
  st.session_state.current_stats = stats
910
- st.success("Data uploaded successfully!")
911
  except Exception as e:
912
- st.error(f"Error loading uploaded file: {str(e)}")
913
  elif 'load_preset' in st.session_state:
914
  year = st.session_state.load_preset
915
  try:
@@ -919,14 +958,14 @@ def main():
919
  stats = get_material_stats(df)
920
  st.session_state.current_df = df
921
  st.session_state.current_stats = stats
922
- st.success(f"{year} data loaded successfully!")
923
  except Exception as e:
924
- st.error(f"Error loading {year} data: {str(e)}")
925
  finally:
926
  del st.session_state.load_preset
927
 
928
  if df is not None and stats is not None:
929
- st.markdown('<div class="section-header">📋 Material Overview</div>', unsafe_allow_html=True)
930
  materials = [k for k in stats.keys() if k != '_total_']
931
  all_metrics = materials + ['_total_']
932
 
@@ -954,7 +993,7 @@ def main():
954
  )
955
  st.caption(f"Daily avg: {info['daily_avg']:,.0f} kg")
956
 
957
- st.markdown('<div class="section-header">📊 Production Trends</div>', unsafe_allow_html=True)
958
  col1, col2 = st.columns([3, 1])
959
  with col2:
960
  time_view = st.selectbox("Time Period", ["daily", "weekly", "monthly"], key="time_view_select")
@@ -965,7 +1004,7 @@ def main():
965
  st.plotly_chart(total_chart, use_container_width=True)
966
  st.markdown('</div>', unsafe_allow_html=True)
967
 
968
- st.markdown('<div class="section-header">🏷️ Materials Analysis</div>', unsafe_allow_html=True)
969
  col1, col2 = st.columns([3, 1])
970
  with col2:
971
  selected_materials = st.multiselect(
@@ -983,21 +1022,22 @@ def main():
983
  st.markdown('</div>', unsafe_allow_html=True)
984
 
985
  if 'shift' in df.columns:
986
- st.markdown('<div class="section-header">🌓 Shift Analysis</div>', unsafe_allow_html=True)
987
  with st.container():
988
  st.markdown('<div class="chart-container">', unsafe_allow_html=True)
989
  shift_chart = create_shift_trend_chart(df, time_view)
990
  st.plotly_chart(shift_chart, use_container_width=True)
991
  st.markdown('</div>', unsafe_allow_html=True)
992
 
993
- st.markdown('<div class="section-header">⚠️ Quality Check</div>', unsafe_allow_html=True)
 
994
  outliers = detect_outliers(df)
995
 
996
- # Create responsive grid using Streamlit columns
997
  materials_list = list(outliers.items())
998
  num_materials = len(materials_list)
999
 
1000
- # Create rows of cards (3-4 per row depending on screen size)
1001
  cols_per_row = min(3, num_materials) if num_materials <= 6 else 4
1002
 
1003
  for i in range(0, num_materials, cols_per_row):
@@ -1009,34 +1049,41 @@ def main():
1009
  material_title = material.replace("_", " ").title()
1010
 
1011
  if info['count'] > 0:
1012
- # Format dates - show first 5, then +X more if needed
1013
- dates_list = info['dates']
1014
- if len(dates_list) <= 5:
1015
- dates_display = '<br/>'.join(dates_list)
1016
- else:
1017
- dates_display = '<br/>'.join(dates_list[:5]) + f'<br/>(+{len(dates_list)-5} more)'
1018
 
1019
  card_html = f'''
1020
  <div class="quality-card card-warning">
1021
- <div class="card-header">
1022
- <span class="material-name">{material_title}</span>
 
 
 
 
 
 
 
1023
  </div>
1024
- <div class="status-badge warning-badge">{info["count"]} Outlier{"s" if info["count"] > 1 else ""}</div>
1025
- <div class="range-text">Normal range: <strong>{info["range"]}</strong></div>
1026
  <div class="dates-section">
1027
- <div class="dates-title">Dates:</div>
1028
- {dates_display}
1029
  </div>
1030
  </div>
1031
  '''
1032
  else:
1033
  card_html = f'''
1034
  <div class="quality-card card-success">
1035
- <div class="card-header">
1036
- <span class="material-name">{material_title}</span>
 
 
 
1037
  </div>
1038
  <div class="success-center">
1039
- <span class="status-badge success-badge">All Values Normal</span>
1040
  </div>
1041
  </div>
1042
  '''
@@ -1046,7 +1093,7 @@ def main():
1046
  add_export_section(df, stats, outliers, model)
1047
 
1048
  if model:
1049
- st.markdown('<div class="section-header">🤖 AI Insights</div>', unsafe_allow_html=True)
1050
  quick_questions = [
1051
  "How does production distribution on weekdays compare to weekends?",
1052
  "Which material exhibits the most volatility in our dataset?",
 
89
  box-shadow: 0 1px 3px rgba(0,0,0,0.1);
90
  margin-bottom: 1rem;
91
  }}
92
+
93
+ /* Updated Quality Check Styles */
94
+ .quality-grid {{
95
+ display: grid;
96
+ grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
97
+ gap: 16px;
98
+ margin-top: 20px;
99
+ }}
100
  .quality-card {{
101
  background: white;
102
  border: 1px solid {DESIGN_SYSTEM['colors']['border']};
103
+ border-radius: 12px;
104
+ padding: 24px;
105
+ min-height: 140px;
106
+ box-shadow: 0 4px 12px rgba(0,0,0,0.08);
107
+ border-left: 4px solid transparent;
108
+ transition: all 0.3s ease;
109
+ position: relative;
110
  }}
111
  .quality-card:hover {{
112
  transform: translateY(-2px);
113
+ box-shadow: 0 8px 25px rgba(0,0,0,0.15);
114
  }}
115
  .card-warning {{
116
+ border-left-color: {DESIGN_SYSTEM['colors']['warning']};
117
  }}
118
  .card-success {{
119
+ border-left-color: {DESIGN_SYSTEM['colors']['success']};
 
 
 
120
  }}
121
+ .card-title {{
122
+ font-size: 16px;
123
  font-weight: 600;
124
  color: {DESIGN_SYSTEM['colors']['text']};
125
+ margin-bottom: 12px;
126
  }}
127
  .status-badge {{
128
  display: inline-block;
129
+ padding: 6px 12px;
130
+ border-radius: 16px;
131
  font-size: 12px;
132
+ font-weight: 600;
133
+ text-transform: uppercase;
134
+ letter-spacing: 0.5px;
135
+ margin-bottom: 12px;
136
  }}
137
+ .status-warning {{
138
+ background: rgba(217, 119, 6, 0.15);
139
  color: {DESIGN_SYSTEM['colors']['warning']};
140
  }}
141
+ .status-success {{
142
+ background: rgba(16, 185, 129, 0.15);
143
  color: {DESIGN_SYSTEM['colors']['success']};
144
  }}
145
+ .outliers-info {{
146
+ display: flex;
147
+ align-items: baseline;
148
+ margin-bottom: 12px;
149
+ }}
150
+ .outliers-count {{
151
+ font-size: 24px;
152
+ font-weight: 700;
153
+ margin-right: 8px;
154
+ }}
155
+ .outliers-count.warning {{
156
+ color: {DESIGN_SYSTEM['colors']['warning']};
157
+ }}
158
+ .outliers-count.success {{
159
+ color: {DESIGN_SYSTEM['colors']['success']};
160
+ }}
161
+ .outliers-text {{
162
  color: #6B7280;
163
+ font-size: 14px;
164
+ }}
165
+ .range-info {{
166
+ background: #F8F9FA;
167
+ padding: 12px;
168
+ border-radius: 8px;
169
+ margin-bottom: 12px;
170
+ font-size: 13px;
171
+ color: #495057;
172
+ }}
173
+ .range-label {{
174
+ font-weight: 600;
175
+ color: {DESIGN_SYSTEM['colors']['text']};
176
+ margin-bottom: 4px;
177
  }}
178
  .dates-section {{
179
+ font-size: 12px;
180
+ color: #6B7280;
181
+ }}
182
+ .dates-label {{
183
  font-size: 11px;
184
  color: #9CA3AF;
185
+ text-transform: uppercase;
186
+ letter-spacing: 0.5px;
187
+ margin-bottom: 8px;
188
  font-weight: 600;
189
+ }}
190
+ .dates-list {{
191
+ line-height: 1.6;
192
  }}
193
  .success-center {{
194
  text-align: center;
195
+ margin-top: 16px;
 
 
 
 
 
 
196
  }}
197
+ .success-message {{
198
+ font-size: 14px;
199
+ color: {DESIGN_SYSTEM['colors']['success']};
200
+ font-weight: 500;
201
  }}
202
+
203
  .stButton > button {{
204
  background: {DESIGN_SYSTEM['colors']['primary']};
205
  color: white;
 
497
  """Showcase our AI capabilities and technical achievements"""
498
 
499
  if model:
500
+ st.markdown('<div class="section-header">AI-Powered Solution</div>', unsafe_allow_html=True)
501
 
502
  # Demonstrate our capabilities
503
+ st.markdown("### **Nilsen Service & Consulting - Technical Achievements**")
504
  outliers = detect_outliers(df)
505
  with st.spinner("Demonstrating our AI capabilities..."):
506
  ai_summary = generate_ai_summary(model, df, stats, outliers)
507
  st.success(ai_summary)
508
 
509
  # Show our system's intelligence
510
+ st.markdown("### **Experience Our Advanced Analytics**")
511
  st.markdown("*See how our AI system provides professional insights for your operations:*")
512
 
513
  demo_questions = [
 
519
  cols = st.columns(len(demo_questions))
520
  for i, question in enumerate(demo_questions):
521
  with cols[i]:
522
+ if st.button(f"{question}", key=f"demo_q_{i}"):
523
  with st.spinner("Our AI analyzing..."):
524
  answer = query_ai(model, stats, question, df)
525
  st.info(f"**Nilsen AI Response:** {answer}")
526
 
527
  # Interactive demonstration
528
+ st.markdown("### **Test Our AI Intelligence**")
529
  col1, col2 = st.columns([3, 1])
530
 
531
  with col1:
 
533
  placeholder="e.g., 'How can your system improve our operational efficiency?'",
534
  key="demo_question")
535
  with col2:
536
+ st.markdown("<br>", unsafe_allow_html=True)
537
+ if st.button("See Our AI in Action", key="demo_btn", type="primary"):
538
  if custom_question:
539
  with st.spinner("Nilsen AI processing..."):
540
  answer = query_ai(model, stats, custom_question, df)
 
547
  st.markdown("---")
548
  st.markdown("""
549
  <div style="background: linear-gradient(135deg, #1E40AF15, #05966925); padding: 1rem; border-radius: 8px; border: 1px solid #1E40AF;">
550
+ <h4>Why Choose Nilsen Service & Consulting?</h4>
551
  <ul>
552
+ <li><strong>Advanced AI Integration:</strong> Cutting-edge analytics for your operations</li>
553
+ <li><strong>Professional Reliability:</strong> Enterprise-grade monitoring systems</li>
554
+ <li><strong>Proven Results:</strong> Data-driven insights that deliver ROI</li>
555
+ <li><strong>Complete Solution:</strong> From data processing to actionable recommendations</li>
556
  </ul>
557
  </div>
558
  """, unsafe_allow_html=True)
559
 
560
  else:
561
+ st.markdown('<div class="section-header">AI-Powered Solution</div>', unsafe_allow_html=True)
562
+ st.error("AI demonstration requires API configuration")
563
+ st.info("**Our AI system provides:** Advanced analytics, predictive insights, automated reporting, and intelligent recommendations for production optimization.")
 
564
 
565
  def query_ai(model, stats, question, df=None):
566
  if not model:
 
844
  return summary_df
845
 
846
  def add_export_section(df, stats, outliers, model):
847
+ st.markdown('<div class="section-header">Export Reports</div>', unsafe_allow_html=True)
848
  if 'export_ready' not in st.session_state:
849
  st.session_state.export_ready = False
850
  if 'pdf_buffer' not in st.session_state:
 
858
  with st.spinner("Generating PDF with AI analysis..."):
859
  st.session_state.pdf_buffer = create_enhanced_pdf_report(df, stats, outliers, model)
860
  st.session_state.export_ready = True
861
+ st.success("PDF report with AI analysis generated successfully!")
862
  except Exception as e:
863
+ st.error(f"PDF generation failed: {str(e)}")
864
  st.session_state.export_ready = False
865
  if st.session_state.export_ready and st.session_state.pdf_buffer:
866
  st.download_button(
867
+ label="Download PDF Report",
868
  data=st.session_state.pdf_buffer,
869
  file_name=f"production_report_ai_{datetime.now().strftime('%Y%m%d_%H%M')}.pdf",
870
  mime="application/pdf",
 
874
  if st.button("Generate CSV Summary", key="generate_csv_btn", type="primary"):
875
  try:
876
  st.session_state.csv_data = create_csv_export(df, stats)
877
+ st.success("CSV summary generated successfully!")
878
  except Exception as e:
879
+ st.error(f"CSV generation failed: {str(e)}")
880
  if st.session_state.csv_data is not None:
881
  csv_string = st.session_state.csv_data.to_csv(index=False)
882
  st.download_button(
883
+ label="Download CSV Summary",
884
  data=csv_string,
885
  file_name=f"production_summary_{datetime.now().strftime('%Y%m%d_%H%M')}.csv",
886
  mime="text/csv",
 
900
  load_css()
901
  st.markdown("""
902
  <div class="main-header">
903
+ <div class="main-title">Production Monitor with AI Insights</div>
904
  <div class="main-subtitle">Nilsen Service & Consulting AS | Real-time Production Analytics & Recommendations</div>
905
  </div>
906
  """, unsafe_allow_html=True)
 
913
  st.session_state.current_stats = None
914
 
915
  with st.sidebar:
916
+ st.markdown("### Data Source")
917
  uploaded_file = st.file_uploader("Upload Production Data", type=['csv'])
918
  st.markdown("---")
919
+ st.markdown("### Quick Load")
920
  col1, col2 = st.columns(2)
921
  with col1:
922
+ if st.button("2024 Data", type="primary", key="load_2024"):
923
  st.session_state.load_preset = "2024"
924
  with col2:
925
+ if st.button("2025 Data", type="primary", key="load_2025"):
926
  st.session_state.load_preset = "2025"
927
  st.markdown("---")
928
  st.markdown("""
 
933
  - `shift`: day/night (optional)
934
  """)
935
  if model:
936
+ st.success("AI Assistant Ready")
937
  else:
938
+ st.warning("AI Assistant Unavailable")
939
 
940
  df = st.session_state.current_df
941
  stats = st.session_state.current_stats
 
946
  stats = get_material_stats(df)
947
  st.session_state.current_df = df
948
  st.session_state.current_stats = stats
949
+ st.success("Data uploaded successfully!")
950
  except Exception as e:
951
+ st.error(f"Error loading uploaded file: {str(e)}")
952
  elif 'load_preset' in st.session_state:
953
  year = st.session_state.load_preset
954
  try:
 
958
  stats = get_material_stats(df)
959
  st.session_state.current_df = df
960
  st.session_state.current_stats = stats
961
+ st.success(f"{year} data loaded successfully!")
962
  except Exception as e:
963
+ st.error(f"Error loading {year} data: {str(e)}")
964
  finally:
965
  del st.session_state.load_preset
966
 
967
  if df is not None and stats is not None:
968
+ st.markdown('<div class="section-header">Material Overview</div>', unsafe_allow_html=True)
969
  materials = [k for k in stats.keys() if k != '_total_']
970
  all_metrics = materials + ['_total_']
971
 
 
993
  )
994
  st.caption(f"Daily avg: {info['daily_avg']:,.0f} kg")
995
 
996
+ st.markdown('<div class="section-header">Production Trends</div>', unsafe_allow_html=True)
997
  col1, col2 = st.columns([3, 1])
998
  with col2:
999
  time_view = st.selectbox("Time Period", ["daily", "weekly", "monthly"], key="time_view_select")
 
1004
  st.plotly_chart(total_chart, use_container_width=True)
1005
  st.markdown('</div>', unsafe_allow_html=True)
1006
 
1007
+ st.markdown('<div class="section-header">Materials Analysis</div>', unsafe_allow_html=True)
1008
  col1, col2 = st.columns([3, 1])
1009
  with col2:
1010
  selected_materials = st.multiselect(
 
1022
  st.markdown('</div>', unsafe_allow_html=True)
1023
 
1024
  if 'shift' in df.columns:
1025
+ st.markdown('<div class="section-header">Shift Analysis</div>', unsafe_allow_html=True)
1026
  with st.container():
1027
  st.markdown('<div class="chart-container">', unsafe_allow_html=True)
1028
  shift_chart = create_shift_trend_chart(df, time_view)
1029
  st.plotly_chart(shift_chart, use_container_width=True)
1030
  st.markdown('</div>', unsafe_allow_html=True)
1031
 
1032
+ # Updated Quality Check Section
1033
+ st.markdown('<div class="section-header">Quality Check</div>', unsafe_allow_html=True)
1034
  outliers = detect_outliers(df)
1035
 
1036
+ # Create quality cards using new modern design
1037
  materials_list = list(outliers.items())
1038
  num_materials = len(materials_list)
1039
 
1040
+ # Create responsive grid
1041
  cols_per_row = min(3, num_materials) if num_materials <= 6 else 4
1042
 
1043
  for i in range(0, num_materials, cols_per_row):
 
1049
  material_title = material.replace("_", " ").title()
1050
 
1051
  if info['count'] > 0:
1052
+ # Show dates in compact format
1053
+ dates_list = info['dates'][:5] # Show max 5 dates
1054
+ dates_display = ', '.join(dates_list)
1055
+ if len(info['dates']) > 5:
1056
+ dates_display += f' (+{len(info["dates"])-5} more)'
 
1057
 
1058
  card_html = f'''
1059
  <div class="quality-card card-warning">
1060
+ <div class="card-title">{material_title}</div>
1061
+ <div class="status-badge status-warning">Warning</div>
1062
+ <div class="outliers-info">
1063
+ <span class="outliers-count warning">{info["count"]}</span>
1064
+ <span class="outliers-text">Outliers</span>
1065
+ </div>
1066
+ <div class="range-info">
1067
+ <div class="range-label">Normal Range</div>
1068
+ <div>{info["range"]}</div>
1069
  </div>
 
 
1070
  <div class="dates-section">
1071
+ <div class="dates-label">Dates</div>
1072
+ <div class="dates-list">{dates_display}</div>
1073
  </div>
1074
  </div>
1075
  '''
1076
  else:
1077
  card_html = f'''
1078
  <div class="quality-card card-success">
1079
+ <div class="card-title">{material_title}</div>
1080
+ <div class="status-badge status-success">Normal</div>
1081
+ <div class="outliers-info">
1082
+ <span class="outliers-count success">0</span>
1083
+ <span class="outliers-text">Outliers</span>
1084
  </div>
1085
  <div class="success-center">
1086
+ <div class="success-message">All values within normal range</div>
1087
  </div>
1088
  </div>
1089
  '''
 
1093
  add_export_section(df, stats, outliers, model)
1094
 
1095
  if model:
1096
+ st.markdown('<div class="section-header">AI Insights</div>', unsafe_allow_html=True)
1097
  quick_questions = [
1098
  "How does production distribution on weekdays compare to weekends?",
1099
  "Which material exhibits the most volatility in our dataset?",