Esmaeilkiani commited on
Commit
5458cab
·
verified ·
1 Parent(s): 0255cc4

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +281 -58
app.py CHANGED
@@ -4,8 +4,10 @@ import folium
4
  from streamlit_folium import folium_static
5
  import jdatetime
6
  import plotly.express as px
7
- import json
8
- from pathlib import Path
 
 
9
 
10
  # تنظیمات اولیه صفحه
11
  st.set_page_config(
@@ -15,39 +17,100 @@ st.set_page_config(
15
  initial_sidebar_state="expanded"
16
  )
17
 
18
- # CSS برای راست به چپ کردن متن‌ها
19
  st.markdown(
20
  """
21
  <style>
 
 
 
 
 
 
22
  .css-1d391kg {
23
  direction: rtl;
24
  }
 
25
  .stButton>button {
26
  float: right;
 
 
 
27
  }
28
- .stSelectbox>div>div {
29
- direction: rtl;
30
- text-align: right;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
  }
32
  </style>
33
  """,
34
  unsafe_allow_html=True
35
  )
36
 
37
- # تعریف داده‌های اولیه
38
  @st.cache_data
39
  def load_initial_data():
40
  data = {
41
- 'مزرعه': ['01-28', '02-19', '02-27', '03-08', '03-30', '03-32'],
42
- 'کانال': ['01', '02', '02', '03', '03', '03'],
43
- 'اداره': [1, 2, 2, 1, 1, 1],
44
- 'واریته': ['CP69', 'CP69', 'CP69', 'CP69', 'IR01-412', 'IRC00-14'],
45
- 'مساحت': [23.83, 24.53, 24.84, 23.17, 23.35, 22.97],
46
- 'چاهک_1_نصب': [False] * 6,
47
- 'چاهک_1_تکنسین': [''] * 6,
48
- 'چاهک_1_تاریخ': [''] * 6,
49
- 'چاهک_1_lat': [0.0] * 6,
50
- 'چاهک_1_lon': [0.0] * 6,
51
  'چاهک_2_نصب': [False] * 6,
52
  'چاهک_2_تکنسین': [''] * 6,
53
  'چاهک_2_تاریخ': [''] * 6,
@@ -68,12 +131,27 @@ TECHNICIANS = [
68
  'امین هنری'
69
  ]
70
 
71
- # عنوان اصلی
72
- st.title("🌱 مدیریت چاهک‌های مزارع نیشکر")
 
 
 
 
 
 
 
 
73
 
74
- # ساید‌بار برای فیلتر کردن
75
  with st.sidebar:
76
- st.header("فیلترها")
 
 
 
 
 
 
 
77
  selected_department = st.selectbox(
78
  "انتخاب اداره",
79
  options=[0, 1, 2, 3, 4],
@@ -90,53 +168,161 @@ if search_term:
90
  mask = (filtered_data['مزرعه'].str.contains(search_term)) | (filtered_data['کانال'].str.contains(search_term))
91
  filtered_data = filtered_data[mask]
92
 
93
- # نمایش آمار کلی
94
  col1, col2, col3 = st.columns(3)
95
  with col1:
96
- total_wells = len(filtered_data) * 2
97
- installed_wells = filtered_data['چاهک_1_نصب'].sum() + filtered_data['چاهک_2_نصب'].sum()
98
- st.metric("کل چاهک‌ها", total_wells)
 
 
 
 
 
 
99
 
100
  with col2:
101
- st.metric("چاهک‌های نصب شده", installed_wells)
 
 
 
 
 
 
 
 
 
102
 
103
  with col3:
104
- st.metric("چاهک‌های باقی‌مانده", total_wells - installed_wells)
 
 
 
 
 
 
 
 
105
 
106
- # نمایش نقشه
107
- st.header("🗺️ نقشه چاهک‌ها")
108
- m = folium.Map(location=[31.3183, 48.6706], zoom_start=10)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
109
 
110
  for idx, row in filtered_data.iterrows():
111
  if row['چاهک_1_نصب'] and row['چاهک_1_lat'] != 0:
112
- folium.Marker(
113
- [row['چاهک_1_lat'], row['چاهک_1_lon']],
114
- popup=f"مزرعه: {row['مزرعه']}<br>چاهک: 1<br>تکنسین: {row['چاهک_1_تکنسین']}<br>تاریخ: {row['چاهک_1_تاریخ']}",
115
- icon=folium.Icon(color='red')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116
  ).add_to(m)
117
 
118
  if row['چاهک_2_نصب'] and row['چاهک_2_lat'] != 0:
119
- folium.Marker(
120
- [row['چاهک_2_lat'], row['چاهک_2_lon']],
121
- popup=f"مزرعه: {row['مزرعه']}<br>چاهک: 2<br>تکنسین: {row['چاهک_2_تکنسین']}<br>تاریخ: {row['چاهک_2_تاریخ']}",
122
- icon=folium.Icon(color='blue')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
123
  ).add_to(m)
124
 
125
- folium_static(m)
 
126
 
127
- # لیست مزارع و ثبت چاهک
128
- st.header("📝 لیست مزارع و ثبت چاهک")
 
 
 
 
 
129
 
130
  for idx, row in filtered_data.iterrows():
131
- with st.expander(f"مزرعه {row['مزرعه']} - کانال {row['کانال']}"):
132
- st.write(f"واریته: {row['واریته']}")
133
- st.write(f"مساحت: {row['مساحت']} هکتار")
 
 
 
 
 
 
 
134
 
135
  col1, col2 = st.columns(2)
136
 
137
  # چاهک 1
138
  with col1:
139
- st.subheader("چاهک 1")
140
  if not row['چاهک_1_نصب']:
141
  if st.button(f"ثبت نصب چاهک 1 - مزرعه {row['مزرعه']}", key=f"well1_{idx}"):
142
  technician = st.selectbox(
@@ -144,8 +330,8 @@ for idx, row in filtered_data.iterrows():
144
  options=TECHNICIANS,
145
  key=f"tech1_{idx}"
146
  )
147
- lat = st.number_input("عرض جغرافیایی", value=31.3183, key=f"lat1_{idx}")
148
- lon = st.number_input("طول جغرافیایی", value=48.6706, key=f"lon1_{idx}")
149
  if st.button("ثبت نهایی", key=f"save1_{idx}"):
150
  st.session_state.farms_data.at[idx, 'چاهک_1_نصب'] = True
151
  st.session_state.farms_data.at[idx, 'چاهک_1_تکنسین'] = technician
@@ -155,11 +341,20 @@ for idx, row in filtered_data.iterrows():
155
  st.success("چاهک 1 با موفقیت ثبت شد")
156
  st.rerun()
157
  else:
158
- st.info(f"نصب شده توسط {row['چاهک_1_تکنسین']} در تاریخ {row['چاهک_1_تاریخ']}")
159
-
160
- # چاهک 2
 
 
 
 
 
 
 
 
 
161
  with col2:
162
- st.subheader("چاهک 2")
163
  if not row['چاهک_2_نصب']:
164
  if st.button(f"ثبت نصب چاهک 2 - مزرعه {row['مزرعه']}", key=f"well2_{idx}"):
165
  technician = st.selectbox(
@@ -167,8 +362,8 @@ for idx, row in filtered_data.iterrows():
167
  options=TECHNICIANS,
168
  key=f"tech2_{idx}"
169
  )
170
- lat = st.number_input("عرض جغرافیایی", value=31.3183, key=f"lat2_{idx}")
171
- lon = st.number_input("طول جغرافیایی", value=48.6706, key=f"lon2_{idx}")
172
  if st.button("ثبت نهایی", key=f"save2_{idx}"):
173
  st.session_state.farms_data.at[idx, 'چاهک_2_نصب'] = True
174
  st.session_state.farms_data.at[idx, 'چاهک_2_تکنسین'] = technician
@@ -178,10 +373,25 @@ for idx, row in filtered_data.iterrows():
178
  st.success("چاهک 2 با موفقیت ثبت شد")
179
  st.rerun()
180
  else:
181
- st.info(f"نصب شده توسط {row['چاهک_2_تکنسین']} در تاریخ {row['چاهک_2_تاریخ']}")
 
 
 
 
 
 
 
 
 
182
 
183
  # نمودار پیشرفت نصب به تفکیک اداره
184
- st.header("📊 گزارش پیشرفت نصب")
 
 
 
 
 
 
185
  progress_data = []
186
  for dept in range(1, 5):
187
  dept_data = st.session_state.farms_data[st.session_state.farms_data['اداره'] == dept]
@@ -193,6 +403,19 @@ for dept in range(1, 5):
193
  })
194
 
195
  progress_df = pd.DataFrame(progress_data)
196
- fig = px.bar(progress_df, x='اداره', y='درصد پیشرفت',
197
- title='درصد پیشرفت نصب چاهک‌ها به تفکیک اداره')
198
- st.plotly_chart(fig)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  from streamlit_folium import folium_static
5
  import jdatetime
6
  import plotly.express as px
7
+ from folium.plugins import HeatMap, Fullscreen, Search
8
+ import branca.colormap as cm
9
+ from datetime import datetime
10
+ import base64
11
 
12
  # تنظیمات اولیه صفحه
13
  st.set_page_config(
 
17
  initial_sidebar_state="expanded"
18
  )
19
 
20
+ # CSS برای ظاهر جذاب و متحرک
21
  st.markdown(
22
  """
23
  <style>
24
+ @import url('https://fonts.googleapis.com/css2?family=Vazirmatn:wght@400;700&display=swap');
25
+
26
+ * {
27
+ font-family: 'Vazirmatn', sans-serif !important;
28
+ }
29
+
30
  .css-1d391kg {
31
  direction: rtl;
32
  }
33
+
34
  .stButton>button {
35
  float: right;
36
+ background: linear-gradient(45deg, #1CB5E0 0%, #000851 100%);
37
+ color: white;
38
+ transition: all 0.3s ease;
39
  }
40
+
41
+ .stButton>button:hover {
42
+ transform: translateY(-2px);
43
+ box-shadow: 0 5px 15px rgba(0,0,0,0.2);
44
+ }
45
+
46
+ .css-1y4p8pa {
47
+ padding: 2rem;
48
+ border-radius: 15px;
49
+ background: rgba(255,255,255,0.95);
50
+ box-shadow: 0 8px 32px 0 rgba(31,38,135,0.37);
51
+ backdrop-filter: blur(4px);
52
+ margin: 1rem 0;
53
+ }
54
+
55
+ .css-1v0mbdj {
56
+ border-radius: 15px;
57
+ box-shadow: 0 4px 12px rgba(0,0,0,0.1);
58
+ transition: all 0.3s ease;
59
+ }
60
+
61
+ .css-1v0mbdj:hover {
62
+ transform: translateY(-3px);
63
+ box-shadow: 0 6px 15px rgba(0,0,0,0.2);
64
+ }
65
+
66
+ /* انیمیشن برای عناوین */
67
+ @keyframes slideIn {
68
+ from {
69
+ transform: translateX(50px);
70
+ opacity: 0;
71
+ }
72
+ to {
73
+ transform: translateX(0);
74
+ opacity: 1;
75
+ }
76
+ }
77
+
78
+ h1, h2, h3 {
79
+ animation: slideIn 0.5s ease-out;
80
+ }
81
+
82
+ /* استایل برای کارت‌های آمار */
83
+ .metric-card {
84
+ background: linear-gradient(135deg, #00B4DB 0%, #0083B0 100%);
85
+ color: white;
86
+ padding: 20px;
87
+ border-radius: 10px;
88
+ text-align: center;
89
+ transition: all 0.3s ease;
90
+ }
91
+
92
+ .metric-card:hover {
93
+ transform: scale(1.05);
94
  }
95
  </style>
96
  """,
97
  unsafe_allow_html=True
98
  )
99
 
100
+ # تعریف داده‌های اولیه با چاهک نصب شده
101
  @st.cache_data
102
  def load_initial_data():
103
  data = {
104
+ 'مزرعه': ['17-09', '02-19', '02-27', '03-08', '03-30', '03-32'],
105
+ 'کانال': ['17', '02', '02', '03', '03', '03'],
106
+ 'اداره': [3, 2, 2, 1, 1, 1],
107
+ 'واریته': ['CP73', 'CP69', 'CP69', 'CP69', 'IR01-412', 'IRC00-14'],
108
+ 'مساحت': [23.09, 24.53, 24.84, 23.17, 23.35, 22.97],
109
+ 'چاهک_1_نصب': [True, False, False, False, False, False],
110
+ 'چاهک_1_تکنسین': ['علی دغاغله', '', '', '', '', ''],
111
+ 'چاهک_1_تاریخ': ['1404/01/16', '', '', '', '', ''],
112
+ 'چاهک_1_lat': [31.504, 0.0, 0.0, 0.0, 0.0, 0.0],
113
+ 'چاهک_1_lon': [48.752, 0.0, 0.0, 0.0, 0.0, 0.0],
114
  'چاهک_2_نصب': [False] * 6,
115
  'چاهک_2_تکنسین': [''] * 6,
116
  'چاهک_2_تاریخ': [''] * 6,
 
131
  'امین هنری'
132
  ]
133
 
134
+ # عنوان اصلی با افکت گرادیان
135
+ st.markdown(
136
+ """
137
+ <h1 style='text-align: center; color: #0083B0; background: -webkit-linear-gradient(45deg, #1CB5E0, #000851);
138
+ -webkit-background-clip: text; -webkit-text-fill-color: transparent; padding: 20px;'>
139
+ 🌱 سامانه مدیریت چاهک‌های مزارع نیشکر
140
+ </h1>
141
+ """,
142
+ unsafe_allow_html=True
143
+ )
144
 
145
+ # ساید‌بار با استایل جدید
146
  with st.sidebar:
147
+ st.markdown(
148
+ """
149
+ <div style='background: linear-gradient(45deg, #1CB5E0 0%, #000851 100%); padding: 20px; border-radius: 10px; color: white;'>
150
+ <h2 style='text-align: center; margin: 0;'>🔍 فیلترها</h2>
151
+ </div>
152
+ """,
153
+ unsafe_allow_html=True
154
+ )
155
  selected_department = st.selectbox(
156
  "انتخاب اداره",
157
  options=[0, 1, 2, 3, 4],
 
168
  mask = (filtered_data['مزرعه'].str.contains(search_term)) | (filtered_data['کانال'].str.contains(search_term))
169
  filtered_data = filtered_data[mask]
170
 
171
+ # نمایش آمار کلی با کارت‌های متحرک
172
  col1, col2, col3 = st.columns(3)
173
  with col1:
174
+ st.markdown(
175
+ f"""
176
+ <div class='metric-card'>
177
+ <h2>{len(filtered_data) * 2}</h2>
178
+ <p>کل چاهک‌ها</p>
179
+ </div>
180
+ """,
181
+ unsafe_allow_html=True
182
+ )
183
 
184
  with col2:
185
+ installed_wells = filtered_data['چاهک_1_نصب'].sum() + filtered_data['چاهک_2_نصب'].sum()
186
+ st.markdown(
187
+ f"""
188
+ <div class='metric-card' style='background: linear-gradient(135deg, #00B09B 0%, #96C93D 100%);'>
189
+ <h2>{installed_wells}</h2>
190
+ <p>چاهک‌های نصب شده</p>
191
+ </div>
192
+ """,
193
+ unsafe_allow_html=True
194
+ )
195
 
196
  with col3:
197
+ st.markdown(
198
+ f"""
199
+ <div class='metric-card' style='background: linear-gradient(135deg, #FF416C 0%, #FF4B2B 100%);'>
200
+ <h2>{len(filtered_data) * 2 - installed_wells}</h2>
201
+ <p>چاهک‌های باقی‌مانده</p>
202
+ </div>
203
+ """,
204
+ unsafe_allow_html=True
205
+ )
206
 
207
+ # نمایش نقشه با تصویر ماهواره‌ای
208
+ st.markdown(
209
+ """
210
+ <h2 style='text-align: right; color: #0083B0;'>🗺️ نقشه چاهک‌ها</h2>
211
+ """,
212
+ unsafe_allow_html=True
213
+ )
214
+
215
+ m = folium.Map(
216
+ location=[31.504, 48.752],
217
+ zoom_start=13,
218
+ tiles='https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',
219
+ attr='Esri',
220
+ name='Satellite'
221
+ )
222
+
223
+ # اضافه کردن لایه OpenStreetMap برای خوانایی بهتر
224
+ folium.TileLayer('OpenStreetMap').add_to(m)
225
+
226
+ # اضافه کردن کنترل لایه‌ها
227
+ folium.LayerControl().add_to(m)
228
+
229
+ # اضافه کردن دکمه تمام صفحه
230
+ Fullscreen().add_to(m)
231
+
232
+ # تعریف CSS برای مارکر چشمک‌زن
233
+ pulse_css = """
234
+ @keyframes pulse {
235
+ 0% { transform: scale(0.95); box-shadow: 0 0 0 0 rgba(0, 131, 176, 0.7); }
236
+ 70% { transform: scale(1); box-shadow: 0 0 0 10px rgba(0, 131, 176, 0); }
237
+ 100% { transform: scale(0.95); box-shadow: 0 0 0 0 rgba(0, 131, 176, 0); }
238
+ }
239
+ .pulsing-marker {
240
+ width: 20px;
241
+ height: 20px;
242
+ background: rgba(0, 131, 176, 0.9);
243
+ border-radius: 50%;
244
+ animation: pulse 2s infinite;
245
+ }
246
+ """
247
+
248
+ # اضافه کردن استایل به نقشه
249
+ m.get_root().header.add_child(folium.Element(f'<style>{pulse_css}</style>'))
250
 
251
  for idx, row in filtered_data.iterrows():
252
  if row['چاهک_1_نصب'] and row['چاهک_1_lat'] != 0:
253
+ popup_html = f"""
254
+ <div style='direction: rtl; text-align: right; padding: 10px;'>
255
+ <h4 style='color: #0083B0; margin: 0;'>مزرعه {row['مزرعه']}</h4>
256
+ <p><strong>چاهک:</strong> 1</p>
257
+ <p><strong>تکنسین:</strong> {row['چاهک_1_تکنسین']}</p>
258
+ <p><strong>تاریخ نصب:</strong> {row['چاهک_1_تاریخ']}</p>
259
+ <p><strong>موقعیت:</strong> {row['چاهک_1_lat']:.6f}°N, {row['چاهک_1_lon']:.6f}°E</p>
260
+ </div>
261
+ """
262
+
263
+ folium.CircleMarker(
264
+ location=[row['چاهک_1_lat'], row['چاهک_1_lon']],
265
+ radius=10,
266
+ popup=folium.Popup(popup_html, max_width=300),
267
+ color='#0083B0',
268
+ fill=True,
269
+ fill_color='#0083B0',
270
+ fill_opacity=0.7,
271
+ weight=2,
272
+ className='pulsing-marker'
273
  ).add_to(m)
274
 
275
  if row['چاهک_2_نصب'] and row['چاهک_2_lat'] != 0:
276
+ popup_html = f"""
277
+ <div style='direction: rtl; text-align: right; padding: 10px;'>
278
+ <h4 style='color: #FF416C; margin: 0;'>مزرعه {row['مزرعه']}</h4>
279
+ <p><strong>چاهک:</strong> 2</p>
280
+ <p><strong>تکنسین:</strong> {row['چاهک_2_تکنسین']}</p>
281
+ <p><strong>تاریخ نصب:</strong> {row['چاهک_2_تاریخ']}</p>
282
+ <p><strong>موقعیت:</strong> {row['چاهک_2_lat']:.6f}°N, {row['چاهک_2_lon']:.6f}°E</p>
283
+ </div>
284
+ """
285
+
286
+ folium.CircleMarker(
287
+ location=[row['چاهک_2_lat'], row['چاهک_2_lon']],
288
+ radius=10,
289
+ popup=folium.Popup(popup_html, max_width=300),
290
+ color='#FF416C',
291
+ fill=True,
292
+ fill_color='#FF416C',
293
+ fill_opacity=0.7,
294
+ weight=2,
295
+ className='pulsing-marker'
296
  ).add_to(m)
297
 
298
+ # نمایش نقشه با اندازه بزرگتر
299
+ folium_static(m, width=1200, height=600)
300
 
301
+ # لیست مزارع و ثبت چاهک با ظاهر جدید
302
+ st.markdown(
303
+ """
304
+ <h2 style='text-align: right; color: #0083B0;'>📝 لیست مزارع و ثبت چاهک</h2>
305
+ """,
306
+ unsafe_allow_html=True
307
+ )
308
 
309
  for idx, row in filtered_data.iterrows():
310
+ with st.expander(f"🌾 مزرعه {row['مزرعه']} - کانال {row['کانال']}", expanded=False):
311
+ st.markdown(
312
+ f"""
313
+ <div style='background: linear-gradient(135deg, #f6f9fc 0%, #f0f4f8 100%); padding: 15px; border-radius: 10px;'>
314
+ <p><strong>واریته:</strong> {row['واریته']}</p>
315
+ <p><strong>مساحت:</strong> {row['مساحت']} هکتار</p>
316
+ </div>
317
+ """,
318
+ unsafe_allow_html=True
319
+ )
320
 
321
  col1, col2 = st.columns(2)
322
 
323
  # چاهک 1
324
  with col1:
325
+ st.markdown("<h3 style='color: #0083B0;'>چاهک 1</h3>", unsafe_allow_html=True)
326
  if not row['چاهک_1_نصب']:
327
  if st.button(f"ثبت نصب چاهک 1 - مزرعه {row['مزرعه']}", key=f"well1_{idx}"):
328
  technician = st.selectbox(
 
330
  options=TECHNICIANS,
331
  key=f"tech1_{idx}"
332
  )
333
+ lat = st.number_input("عرض جغرافیایی", value=31.504, key=f"lat1_{idx}")
334
+ lon = st.number_input("طول جغرافیایی", value=48.752, key=f"lon1_{idx}")
335
  if st.button("ثبت نهایی", key=f"save1_{idx}"):
336
  st.session_state.farms_data.at[idx, 'چاهک_1_نصب'] = True
337
  st.session_state.farms_data.at[idx, 'چاهک_1_تکنسین'] = technician
 
341
  st.success("چاهک 1 با موفقیت ثبت شد")
342
  st.rerun()
343
  else:
344
+ st.markdown(
345
+ f"""
346
+ <div style='background: #e3f2fd; padding: 15px; border-radius: 10px;'>
347
+ <p>✅ نصب شده توسط {row['چاهک_1_تکنسین']}</p>
348
+ <p>📅 تاریخ نصب: {row['چاهک_1_تاریخ']}</p>
349
+ <p>📍 موقعیت: {row['چاهک_1_lat']:.6f}°N, {row['چاهک_1_lon']:.6f}°E</p>
350
+ </div>
351
+ """,
352
+ unsafe_allow_html=True
353
+ )
354
+
355
+ # چاهک 2 (مشابه چاهک 1)
356
  with col2:
357
+ st.markdown("<h3 style='color: #FF416C;'>چاهک 2</h3>", unsafe_allow_html=True)
358
  if not row['چاهک_2_نصب']:
359
  if st.button(f"ثبت نصب چاهک 2 - مزرعه {row['مزرعه']}", key=f"well2_{idx}"):
360
  technician = st.selectbox(
 
362
  options=TECHNICIANS,
363
  key=f"tech2_{idx}"
364
  )
365
+ lat = st.number_input("عرض جغرافیایی", value=31.504, key=f"lat2_{idx}")
366
+ lon = st.number_input("طول جغرافیایی", value=48.752, key=f"lon2_{idx}")
367
  if st.button("ثبت نهایی", key=f"save2_{idx}"):
368
  st.session_state.farms_data.at[idx, 'چاهک_2_نصب'] = True
369
  st.session_state.farms_data.at[idx, 'چاهک_2_تکنسین'] = technician
 
373
  st.success("چاهک 2 با موفقیت ثبت شد")
374
  st.rerun()
375
  else:
376
+ st.markdown(
377
+ f"""
378
+ <div style='background: #ffe0e6; padding: 15px; border-radius: 10px;'>
379
+ <p>✅ نصب شده توسط {row['چاهک_2_تکنسین']}</p>
380
+ <p>📅 تاریخ نصب: {row['چاهک_2_تاریخ']}</p>
381
+ <p>📍 موقعیت: {row['چاهک_2_lat']:.6f}°N, {row['چاهک_2_lon']:.6f}°E</p>
382
+ </div>
383
+ """,
384
+ unsafe_allow_html=True
385
+ )
386
 
387
  # نمودار پیشرفت نصب به تفکیک اداره
388
+ st.markdown(
389
+ """
390
+ <h2 style='text-align: right; color: #0083B0;'>📊 گزارش پیشرفت نصب</h2>
391
+ """,
392
+ unsafe_allow_html=True
393
+ )
394
+
395
  progress_data = []
396
  for dept in range(1, 5):
397
  dept_data = st.session_state.farms_data[st.session_state.farms_data['اداره'] == dept]
 
403
  })
404
 
405
  progress_df = pd.DataFrame(progress_data)
406
+ fig = px.bar(
407
+ progress_df,
408
+ x='اداره',
409
+ y='درصد پیشرفت',
410
+ title='درصد پیشرفت نصب چاهک‌ها به تفکیک اداره',
411
+ color='درصد پیشرفت',
412
+ color_continuous_scale='Viridis',
413
+ template='plotly_white'
414
+ )
415
+ fig.update_layout(
416
+ plot_bgcolor='rgba(0,0,0,0)',
417
+ paper_bgcolor='rgba(0,0,0,0)',
418
+ font_family='Vazirmatn',
419
+ title_x=0.5
420
+ )
421
+ st.plotly_chart(fig, use_container_width=True)