EGYADMIN commited on
Commit
3d20a1c
·
verified ·
1 Parent(s): 535bdcc

Upload 113 files

Browse files
app.py CHANGED
@@ -144,118 +144,199 @@ except Exception as e:
144
  # إضافة Font Awesome وأي أصول خارجية أخرى
145
  st.markdown("""
146
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
 
 
 
147
  """, unsafe_allow_html=True)
148
 
149
  # إضافة CSS المخصص
150
  st.markdown("""
151
  <style>
152
- /* تعديل الاتجاه للدعم العربي */
153
- .css-18e3th9, .css-1d391kg, .stMarkdown, .stTextArea, .stButton, .stTextInput, .stSelectbox, .stRadio {
154
- direction: rtl;
155
- text-align: right;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
156
  }
157
 
158
  /* تحسين مظهر العناوين */
159
- h1, h2, h3, h4 {
160
- color: #1E88E5;
 
 
161
  }
162
 
163
  /* تخصيص عنوان التطبيق */
164
  .app-title {
165
- font-size: 2.2rem;
166
- font-weight: bold;
167
- text-align: center;
168
- color: #1E88E5;
169
- margin-bottom: 1rem;
170
- text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.1);
171
- background: linear-gradient(90deg, #1976D2, #64B5F6);
172
- -webkit-background-clip: text;
173
- -webkit-text-fill-color: transparent;
 
 
174
  }
175
 
176
- /* تخصيص الشريط الجانبي */
177
- .sidebar .sidebar-content {
178
- background-color: #f8f9fa;
 
 
 
 
 
 
179
  }
180
 
181
- /* تخصيص الأقسام */
182
- .section-card {
183
- background-color: #f9f9f9;
184
- border-radius: 10px;
185
- padding: 20px;
186
- box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
187
- margin-bottom: 20px;
 
 
 
 
 
 
 
 
 
 
 
 
 
188
  }
189
 
190
- /* تخصيص الأزرار */
 
 
 
 
 
 
 
 
 
191
  .stButton>button {
192
- border-radius: 5px;
193
- background-color: #1E88E5;
194
- color: white;
195
- font-weight: bold;
196
- border: none;
197
- padding: 0.5rem 1rem;
198
- transition: all 0.3s ease;
 
199
  }
200
 
201
  .stButton>button:hover {
202
- background-color: #1565C0;
203
- box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
204
  }
205
 
206
  /* تخصيص المؤشرات */
207
  .indicator {
208
- padding: 1rem;
209
- border-radius: 10px;
210
- background-color: #f5f5f5;
211
  text-align: center;
212
- box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
 
 
 
 
 
 
 
213
  }
214
 
215
  .indicator-value {
216
- font-size: 2rem;
217
- font-weight: bold;
218
  margin-bottom: 0.5rem;
 
 
 
 
219
  }
220
 
221
  .indicator-label {
222
  font-size: 1rem;
223
- color: #666;
224
- }
225
-
226
- /* تخصيص البطاقات */
227
- .card {
228
- background-color: white;
229
- border-radius: 10px;
230
- padding: 15px;
231
- box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
232
- margin-bottom: 15px;
233
- border-right: 4px solid #1E88E5;
234
- }
235
-
236
- .card-title {
237
- font-weight: bold;
238
- color: #1E88E5;
239
- margin-bottom: 10px;
240
  }
241
 
 
242
  .card-metrics {
243
  display: flex;
244
  justify-content: space-between;
 
 
 
245
  }
246
 
247
  .card-metric {
248
  text-align: center;
 
 
 
 
 
249
  }
250
 
251
  .card-metric-value {
252
- font-weight: bold;
253
  font-size: 1.5rem;
254
  }
255
 
256
  .card-metric-label {
257
- font-size: 0.8rem;
258
- color: #666;
 
259
  }
260
  </style>
261
  """, unsafe_allow_html=True)
@@ -276,6 +357,7 @@ from modules.voice_narration.voice_narration_app import VoiceNarrationApp
276
  from modules.achievements.achievements_app import AchievementsApp
277
  from modules.ai_finetuning.finetuning_app import FinetuningApp
278
  from modules.document_comparison.comparison_app import DocumentComparisonApp
 
279
 
280
  # إنشاء مجلدات البيانات الضرورية
281
  create_directory_if_not_exists(get_data_folder())
@@ -311,8 +393,9 @@ def main():
311
  resources_app.render()
312
 
313
  elif selected_module == "تحليل المستندات":
314
- # تقديم واجهة تحليل المستندات
315
- render_document_analysis()
 
316
 
317
  elif selected_module == "مقارنة المستندات":
318
  # تقديم واجهة مقارنة المستندات
@@ -412,32 +495,48 @@ def render_homepage():
412
  with col1:
413
  st.markdown("""
414
  <div class="indicator">
415
- <div class="indicator-value" style="color: #1E88E5;">24</div>
416
  <div class="indicator-label">المناقصات النشطة</div>
 
 
 
 
417
  </div>
418
  """, unsafe_allow_html=True)
419
 
420
  with col2:
421
  st.markdown("""
422
  <div class="indicator">
423
- <div class="indicator-value" style="color: #43A047;">8</div>
424
  <div class="indicator-label">مشاريع قيد التنفيذ</div>
 
 
 
 
425
  </div>
426
  """, unsafe_allow_html=True)
427
 
428
  with col3:
429
  st.markdown("""
430
  <div class="indicator">
431
- <div class="indicator-value" style="color: #FB8C00;">12</div>
432
  <div class="indicator-label">مستندات قيد التحليل</div>
 
 
 
 
433
  </div>
434
  """, unsafe_allow_html=True)
435
 
436
  with col4:
437
  st.markdown("""
438
  <div class="indicator">
439
- <div class="indicator-value" style="color: #E53935;">5</div>
440
  <div class="indicator-label">تنبيهات تتطلب الاهتمام</div>
 
 
 
 
441
  </div>
442
  """, unsafe_allow_html=True)
443
 
@@ -516,46 +615,202 @@ def render_homepage():
516
  st.markdown("### الوصول السريع")
517
 
518
  st.markdown("""
519
- <div style="display: grid; gap: 10px;">
520
- <button style="background-color: #1E88E5; color: white; border: none; border-radius: 5px; padding: 10px; text-align: right; cursor: pointer; font-weight: bold;">
521
- <i class="fas fa-file-alt" style="margin-left: 10px;"></i> تحليل مستند جديد
522
- </button>
523
-
524
- <button style="background-color: #43A047; color: white; border: none; border-radius: 5px; padding: 10px; text-align: right; cursor: pointer; font-weight: bold;">
525
- <i class="fas fa-calculator" style="margin-left: 10px;"></i> حساب تكاليف مشروع
526
- </button>
527
-
528
- <button style="background-color: #FB8C00; color: white; border: none; border-radius: 5px; padding: 10px; text-align: right; cursor: pointer; font-weight: bold;">
529
- <i class="fas fa-exclamation-triangle" style="margin-left: 10px;"></i> تقييم مخاطر العقد
530
- </button>
531
-
532
- <button style="background-color: #8E24AA; color: white; border: none; border-radius: 5px; padding: 10px; text-align: right; cursor: pointer; font-weight: bold;">
533
- <i class="fas fa-map-marker-alt" style="margin-left: 10px;"></i> استعراض خريطة المشاريع
534
- </button>
535
-
536
- <button style="background-color: #546E7A; color: white; border: none; border-radius: 5px; padding: 10px; text-align: right; cursor: pointer; font-weight: bold;">
537
- <i class="fas fa-chart-bar" style="margin-left: 10px;"></i> إنشاء تقارير تحليلية
538
- </button>
 
 
 
 
 
539
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
540
  """, unsafe_allow_html=True)
541
 
542
  st.markdown("### آخر التنبيهات")
543
 
544
  st.markdown("""
545
- <div style="background-color: #FFEBEE; border-right: 3px solid #E53935; padding: 10px; margin-bottom: 10px; border-radius: 5px;">
546
- <div style="font-weight: bold; color: #B71C1C;">انتهاء موعد تقديم المناقصة</div>
547
- <div style="font-size: 0.9rem;">مشروع إنشاء الطريق السريع - متبقي 3 أيام</div>
548
- </div>
549
-
550
- <div style="background-color: #FFF8E1; border-right: 3px solid #FFA000; padding: 10px; margin-bottom: 10px; border-radius: 5px;">
551
- <div style="font-weight: bold; color: #FF6F00;">تغيير في شروط المناقصة</div>
552
- <div style="font-size: 0.9rem;">تم تحديث مستندات مشروع شبكة الصرف الصحي</div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
553
  </div>
554
 
555
- <div style="background-color: #E8F5E9; border-right: 3px solid #43A047; padding: 10px; margin-bottom: 10px; border-radius: 5px;">
556
- <div style="font-weight: bold; color: #2E7D32;">إكمال تحليل المستند</div>
557
- <div style="font-size: 0.9rem;">اكتمل تحليل عقد بناء المدارس بنجاح</div>
558
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
559
  """, unsafe_allow_html=True)
560
 
561
  # معلومات حول النظام
@@ -577,121 +832,303 @@ def render_homepage():
577
  """, unsafe_allow_html=True)
578
 
579
 
580
- def render_document_analysis():
581
- """عرض واجهة تحليل المستندات"""
582
- st.markdown("<h1 class='app-title'>تحليل المستندات</h1>", unsafe_allow_html=True)
 
583
 
584
  st.markdown("""
585
- <div class="section-card">
586
- <p>استخدم هذه الوحدة لتحليل مستندات العقود والمناقصات باستخدام تقنيات الذكاء الاصطناعي المتقدمة.
587
- يمكنك تحميل المستندات بتنسيقات PDF أو Word وسيقوم النظام بتحليلها واستخراج المعلومات المهمة مثل الشروط والتكاليف والمخاطر والتزاماتك كمقاول.</p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
588
  </div>
589
- """, unsafe_allow_html=True)
590
-
591
- # أدوات التحليل
592
- st.markdown("### أدوات التحليل:", unsafe_allow_html=True)
593
 
594
- col1, col2, col3 = st.columns(3)
595
-
596
- with col1:
597
- st.markdown("""
598
- <div class="card">
599
- <div class="card-title">تحليل العقد الشامل</div>
600
- <p>تحليل شامل للعقد باستخدام Claude AI لاستخراج جميع البنود والشروط والالتزامات والمواعيد النهائية.</p>
601
- </div>
602
- """, unsafe_allow_html=True)
603
 
604
- if st.button("تحليل جديد", key="btn_complete_analysis"):
605
- # هنا سيتم استدعاء وحدة تحليل العقد الشامل
606
- st.session_state.analysis_type = "complete"
607
- st.session_state.show_document_upload = True
608
- st.rerun()
609
-
610
- with col2:
611
- st.markdown("""
612
- <div class="card">
613
- <div class="card-title">تحليل جداول الكميات</div>
614
- <p>تحليل متخصص لجداول الكميات (BOQ) لاستخراج قوائم المواد والكميات والأسعار والتكاليف الإجمالية.</p>
615
- </div>
616
- """, unsafe_allow_html=True)
617
 
618
- if st.button("تحليل جديد", key="btn_boq_analysis"):
619
- # هنا سيتم استدعاء وحدة تحليل جداول الكميات
620
- st.session_state.analysis_type = "boq"
621
- st.session_state.show_document_upload = True
622
- st.rerun()
623
-
624
- with col3:
625
- st.markdown("""
626
- <div class="card">
627
- <div class="card-title">تحليل الشروط والأحكام</div>
628
- <p>تحليل متخصص للشروط والأحكام في العقد لتحديد الشروط الغير عادية أو المقيدة والمخاطر القانونية.</p>
629
- </div>
630
- """, unsafe_allow_html=True)
631
 
632
- if st.button("تحليل جديد", key="btn_terms_analysis"):
633
- # هنا سيتم استدعاء وحدة تحليل الشروط والأحكام
634
- st.session_state.analysis_type = "terms"
635
- st.session_state.show_document_upload = True
636
- st.rerun()
637
-
638
- # التحليلات الأخيرة
639
- st.markdown("### التحليلات الأخيرة")
640
-
641
- st.markdown("""
642
- <table style="width: 100%; border-collapse: collapse; margin-top: 20px;">
643
- <thead>
644
- <tr style="background-color: #f5f5f5;">
645
- <th style="padding: 12px; text-align: right; border-bottom: 2px solid #ddd;">اسم المستند</th>
646
- <th style="padding: 12px; text-align: right; border-bottom: 2px solid #ddd;">نوع التحليل</th>
647
- <th style="padding: 12px; text-align: right; border-bottom: 2px solid #ddd;">تاريخ التحليل</th>
648
- <th style="padding: 12px; text-align: right; border-bottom: 2px solid #ddd;">الحالة</th>
649
- <th style="padding: 12px; text-align: right; border-bottom: 2px solid #ddd;">الإجراءات</th>
650
- </tr>
651
- </thead>
652
- <tbody>
653
- <tr>
654
- <td style="padding: 12px; text-align: right; border-bottom: 1px solid #ddd;">عقد إنشاء طريق سريع.pdf</td>
655
- <td style="padding: 12px; text-align: right; border-bottom: 1px solid #ddd;">تحليل شامل</td>
656
- <td style="padding: 12px; text-align: right; border-bottom: 1px solid #ddd;">2023-03-25</td>
657
- <td style="padding: 12px; text-align: right; border-bottom: 1px solid #ddd;"><span style="color: #4CAF50; font-weight: bold;">مكتمل</span></td>
658
- <td style="padding: 12px; text-align: right; border-bottom: 1px solid #ddd;">
659
- <button style="background-color: #1E88E5; color: white; border: none; border-radius: 3px; padding: 5px 10px; margin-left: 5px; cursor: pointer;">عرض</button>
660
- <button style="background-color: #78909C; color: white; border: none; border-radius: 3px; padding: 5px 10px; cursor: pointer;">تنزيل التقرير</button>
661
- </td>
662
- </tr>
663
- <tr style="background-color: #f9f9f9;">
664
- <td style="padding: 12px; text-align: right; border-bottom: 1px solid #ddd;">جداول كميات مشروع صرف صحي.xlsx</td>
665
- <td style="padding: 12px; text-align: right; border-bottom: 1px solid #ddd;">تحليل جداول الكميات</td>
666
- <td style="padding: 12px; text-align: right; border-bottom: 1px solid #ddd;">2023-03-23</td>
667
- <td style="padding: 12px; text-align: right; border-bottom: 1px solid #ddd;"><span style="color: #4CAF50; font-weight: bold;">مكتمل</span></td>
668
- <td style="padding: 12px; text-align: right; border-bottom: 1px solid #ddd;">
669
- <button style="background-color: #1E88E5; color: white; border: none; border-radius: 3px; padding: 5px 10px; margin-left: 5px; cursor: pointer;">عرض</button>
670
- <button style="background-color: #78909C; color: white; border: none; border-radius: 3px; padding: 5px 10px; cursor: pointer;">تنزيل التقرير</button>
671
- </td>
672
- </tr>
673
- <tr>
674
- <td style="padding: 12px; text-align: right; border-bottom: 1px solid #ddd;">شروط وأحكام عقد بناء مدارس.pdf</td>
675
- <td style="padding: 12px; text-align: right; border-bottom: 1px solid #ddd;">تحليل الشروط والأحكام</td>
676
- <td style="padding: 12px; text-align: right; border-bottom: 1px solid #ddd;">2023-03-20</td>
677
- <td style="padding: 12px; text-align: right; border-bottom: 1px solid #ddd;"><span style="color: #4CAF50; font-weight: bold;">مكتمل</span></td>
678
- <td style="padding: 12px; text-align: right; border-bottom: 1px solid #ddd;">
679
- <button style="background-color: #1E88E5; color: white; border: none; border-radius: 3px; padding: 5px 10px; margin-left: 5px; cursor: pointer;">عرض</button>
680
- <button style="background-color: #78909C; color: white; border: none; border-radius: 3px; padding: 5px 10px; cursor: pointer;">تنزيل التقرير</button>
681
- </td>
682
- </tr>
683
- <tr style="background-color: #f9f9f9;">
684
- <td style="padding: 12px; text-align: right; border-bottom: 1px solid #ddd;">ملحق عقد مشروع كباري.pdf</td>
685
- <td style="padding: 12px; text-align: right; border-bottom: 1px solid #ddd;">تحليل شامل</td>
686
- <td style="padding: 12px; text-align: right; border-bottom: 1px solid #ddd;">2023-03-18</td>
687
- <td style="padding: 12px; text-align: right; border-bottom: 1px solid #ddd;"><span style="color: #FB8C00; font-weight: bold;">قيد المعالجة</span></td>
688
- <td style="padding: 12px; text-align: right; border-bottom: 1px solid #ddd;">
689
- <button style="background-color: #9E9E9E; color: white; border: none; border-radius: 3px; padding: 5px 10px; margin-left: 5px; cursor: pointer;" disabled>عرض</button>
690
- <button style="background-color: #9E9E9E; color: white; border: none; border-radius: 3px; padding: 5px 10px; cursor: pointer;" disabled>تنزيل التقرير</button>
691
- </td>
692
- </tr>
693
- </tbody>
694
- </table>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
695
  """, unsafe_allow_html=True)
696
 
697
  # إحصائيات التحليل
@@ -701,45 +1138,62 @@ def render_document_analysis():
701
 
702
  with col1:
703
  st.markdown("""
704
- <div style="padding: 20px; background-color: #f5f5f5; border-radius: 10px; height: 100%;">
705
- <h4 style="color: #1E88E5; margin-bottom: 15px;">توزيع أنواع المستندات</h4>
706
- <div style="margin-bottom: 15px;">
707
- <div style="display: flex; justify-content: space-between; margin-bottom: 5px;">
708
- <span>عقود ومناقصات</span>
709
- <span>45%</span>
710
- </div>
711
- <div style="height: 10px; background-color: #e0e0e0; border-radius: 5px;">
712
- <div style="height: 100%; width: 45%; background-color: #1E88E5; border-radius: 5px;"></div>
713
- </div>
714
  </div>
715
 
716
- <div style="margin-bottom: 15px;">
717
- <div style="display: flex; justify-content: space-between; margin-bottom: 5px;">
718
- <span>جداول كميات</span>
719
- <span>30%</span>
 
 
 
 
 
 
 
 
720
  </div>
721
- <div style="height: 10px; background-color: #e0e0e0; border-radius: 5px;">
722
- <div style="height: 100%; width: 30%; background-color: #43A047; border-radius: 5px;"></div>
 
 
 
 
 
 
 
 
 
 
723
  </div>
724
- </div>
725
-
726
- <div style="margin-bottom: 15px;">
727
- <div style="display: flex; justify-content: space-between; margin-bottom: 5px;">
728
- <span>شروط وأحكام</span>
729
- <span>15%</span>
730
- </div>
731
- <div style="height: 10px; background-color: #e0e0e0; border-radius: 5px;">
732
- <div style="height: 100%; width: 15%; background-color: #FB8C00; border-radius: 5px;"></div>
733
- </div>
734
- </div>
735
-
736
- <div style="margin-bottom: 15px;">
737
- <div style="display: flex; justify-content: space-between; margin-bottom: 5px;">
738
- <span>مستندات أخرى</span>
739
- <span>10%</span>
740
  </div>
741
- <div style="height: 10px; background-color: #e0e0e0; border-radius: 5px;">
742
- <div style="height: 100%; width: 10%; background-color: #78909C; border-radius: 5px;"></div>
 
 
 
 
 
 
 
 
 
 
743
  </div>
744
  </div>
745
  </div>
@@ -747,48 +1201,189 @@ def render_document_analysis():
747
 
748
  with col2:
749
  st.markdown("""
750
- <div style="padding: 20px; background-color: #f5f5f5; border-radius: 10px; height: 100%;">
751
- <h4 style="color: #1E88E5; margin-bottom: 15px;">إحصائيات التحليل الشهرية</h4>
752
- <div style="display: flex; justify-content: space-between; text-align: center;">
753
- <div>
754
- <div style="font-size: 2rem; font-weight: bold; color: #1E88E5;">42</div>
755
- <div style="color: #666;">مستند تم تحليله</div>
 
 
 
756
  </div>
757
- <div>
758
- <div style="font-size: 2rem; font-weight: bold; color: #43A047;">38</div>
759
- <div style="color: #666;">تحليل ناجح</div>
760
  </div>
761
- <div>
762
- <div style="font-size: 2rem; font-weight: bold; color: #FB8C00;">4</div>
763
- <div style="color: #666;">تحليل غير مكتمل</div>
764
  </div>
765
  </div>
766
 
767
- <h4 style="color: #1E88E5; margin-top: 20px; margin-bottom: 15px;">متوسط وقت المعالجة</h4>
768
- <div style="display: flex; align-items: center; margin-bottom: 10px;">
769
- <div style="width: 150px;">تحليل شامل:</div>
770
- <div style="flex-grow: 1; height: 8px; background-color: #e0e0e0; border-radius: 5px;">
771
- <div style="height: 100%; width: 80%; background-color: #1E88E5; border-radius: 5px;"></div>
772
- </div>
773
- <div style="width: 50px; text-align: left; padding-left: 10px;">2:30</div>
774
  </div>
775
 
776
- <div style="display: flex; align-items: center; margin-bottom: 10px;">
777
- <div style="width: 150px;">جداول الكميات:</div>
778
- <div style="flex-grow: 1; height: 8px; background-color: #e0e0e0; border-radius: 5px;">
779
- <div style="height: 100%; width: 50%; background-color: #43A047; border-radius: 5px;"></div>
 
 
 
 
 
 
 
780
  </div>
781
- <div style="width: 50px; text-align: left; padding-left: 10px;">1:45</div>
782
- </div>
783
-
784
- <div style="display: flex; align-items: center;">
785
- <div style="width: 150px;">الشروط والأحكام:</div>
786
- <div style="flex-grow: 1; height: 8px; background-color: #e0e0e0; border-radius: 5px;">
787
- <div style="height: 100%; width: 60%; background-color: #FB8C00; border-radius: 5px;"></div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
788
  </div>
789
- <div style="width: 50px; text-align: left; padding-left: 10px;">2:00</div>
790
  </div>
791
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
792
  """, unsafe_allow_html=True)
793
 
794
 
 
144
  # إضافة Font Awesome وأي أصول خارجية أخرى
145
  st.markdown("""
146
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
147
+ <link href="https://fonts.googleapis.com/css2?family=Almarai:wght@300;400;700;800&display=swap" rel="stylesheet">
148
+ <link href="https://fonts.googleapis.com/css2?family=Tajawal:wght@300;400;500;700;800;900&display=swap" rel="stylesheet">
149
+ <link href="https://fonts.googleapis.com/css2?family=Cairo:wght@300;400;500;600;700;800;900;1000&display=swap" rel="stylesheet">
150
  """, unsafe_allow_html=True)
151
 
152
  # إضافة CSS المخصص
153
  st.markdown("""
154
  <style>
155
+ :root {
156
+ --primary-color: #0B6E4F;
157
+ --secondary-color: #08603a;
158
+ --primary-light: rgba(11, 110, 79, 0.1);
159
+ --primary-gradient: linear-gradient(135deg, #0B6E4F 0%, #08875D 100%);
160
+ --accent-color: #FFB100;
161
+ --accent-light: rgba(255, 177, 0, 0.1);
162
+ --tertiary-color: #5754FF;
163
+ --quaternary-color: #f43f5e;
164
+ --success-color: #10b981;
165
+ --warning-color: #f59e0b;
166
+ --danger-color: #ef4444;
167
+ --gray-100: #f3f4f6;
168
+ --gray-200: #e5e7eb;
169
+ --gray-300: #d1d5db;
170
+ --gray-400: #9ca3af;
171
+ --gray-500: #6b7280;
172
+ --gray-600: #4b5563;
173
+ --gray-700: #374151;
174
+ --gray-800: #1f2937;
175
+ --gray-900: #111827;
176
+ }
177
+
178
+ /* تعديل الاتجاه للدعم العربي والخط */
179
+ body, .css-18e3th9, .css-1d391kg, .stMarkdown, .stTextArea, .stButton, .stTextInput, .stSelectbox, .stRadio {
180
+ direction: rtl !important;
181
+ text-align: right !important;
182
+ font-family: 'Almarai', 'Tajawal', sans-serif !important;
183
  }
184
 
185
  /* تحسين مظهر العناوين */
186
+ h1, h2, h3, h4, h5 {
187
+ font-family: 'Cairo', 'Almarai', sans-serif !important;
188
+ color: var(--primary-color) !important;
189
+ font-weight: 700 !important;
190
  }
191
 
192
  /* تخصيص عنوان التطبيق */
193
  .app-title {
194
+ font-size: 2.5rem !important;
195
+ font-weight: 800 !important;
196
+ text-align: center !important;
197
+ margin-bottom: 1.5rem !important;
198
+ text-shadow: 1px 2px 2px rgba(0, 0, 0, 0.1) !important;
199
+ background: linear-gradient(90deg, var(--primary-color), var(--secondary-color)) !important;
200
+ -webkit-background-clip: text !important;
201
+ -webkit-text-fill-color: transparent !important;
202
+ background-clip: text !important;
203
+ position: relative !important;
204
+ padding-bottom: 1rem !important;
205
  }
206
 
207
+ .app-title::after {
208
+ content: '' !important;
209
+ position: absolute !important;
210
+ bottom: 0 !important;
211
+ right: 25% !important;
212
+ width: 50% !important;
213
+ height: 4px !important;
214
+ background: linear-gradient(90deg, var(--accent-color), var(--primary-color)) !important;
215
+ border-radius: 4px !important;
216
  }
217
 
218
+ /* تعديل الشعار الرئيسي */
219
+ .main-logo {
220
+ text-align: center !important;
221
+ margin-bottom: 2rem !important;
222
+ }
223
+
224
+ /* تحسين البطاقات والكروت */
225
+ .card {
226
+ background-color: white !important;
227
+ border-radius: 12px !important;
228
+ padding: 1.5rem !important;
229
+ margin-bottom: 1.5rem !important;
230
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.05) !important;
231
+ border: 1px solid var(--gray-200) !important;
232
+ transition: all 0.3s ease !important;
233
+ }
234
+
235
+ .card:hover {
236
+ box-shadow: 0 10px 25px rgba(0, 0, 0, 0.08) !important;
237
+ transform: translateY(-5px) !important;
238
  }
239
 
240
+ .card-title {
241
+ color: var(--primary-color) !important;
242
+ font-weight: 700 !important;
243
+ font-size: 1.4rem !important;
244
+ margin-bottom: 1rem !important;
245
+ border-right: 4px solid var(--primary-color) !important;
246
+ padding-right: 10px !important;
247
+ }
248
+
249
+ /* تعديل مظهر الأزرار */
250
  .stButton>button {
251
+ background: var(--primary-gradient) !important;
252
+ color: white !important;
253
+ border: none !important;
254
+ padding: 0.7rem 1.2rem !important;
255
+ border-radius: 8px !important;
256
+ font-weight: 600 !important;
257
+ box-shadow: 0 4px 10px rgba(11, 110, 79, 0.2) !important;
258
+ transition: all 0.3s ease !important;
259
  }
260
 
261
  .stButton>button:hover {
262
+ box-shadow: 0 6px 15px rgba(11, 110, 79, 0.3) !important;
263
+ transform: translateY(-2px) !important;
264
+ }
265
+
266
+ /* تخصيص الشريط الجانبي */
267
+ .sidebar .sidebar-content {
268
+ background-color: white;
269
+ }
270
+
271
+ /* تخصيص الأقسام */
272
+ .section-card {
273
+ background-color: white;
274
+ border-radius: 12px;
275
+ padding: 1.5rem;
276
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.05);
277
+ margin-bottom: 1.5rem;
278
+ border: 1px solid var(--gray-200);
279
  }
280
 
281
  /* تخصيص المؤشرات */
282
  .indicator {
283
+ padding: 1.2rem;
284
+ border-radius: 12px;
285
+ background: linear-gradient(135deg, white, var(--gray-100));
286
  text-align: center;
287
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.05);
288
+ border: 1px solid var(--gray-200);
289
+ transition: all 0.3s ease;
290
+ }
291
+
292
+ .indicator:hover {
293
+ transform: translateY(-5px);
294
+ box-shadow: 0 8px 25px rgba(0, 0, 0, 0.08);
295
  }
296
 
297
  .indicator-value {
298
+ font-size: 2.2rem;
299
+ font-weight: 800;
300
  margin-bottom: 0.5rem;
301
+ background: var(--primary-gradient);
302
+ -webkit-background-clip: text;
303
+ -webkit-text-fill-color: transparent;
304
+ background-clip: text;
305
  }
306
 
307
  .indicator-label {
308
  font-size: 1rem;
309
+ font-weight: 600;
310
+ color: var(--gray-700);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
311
  }
312
 
313
+ /* تخصيص البطاقات - استخدام المعرفة المسبقة من أعلى */
314
  .card-metrics {
315
  display: flex;
316
  justify-content: space-between;
317
+ margin-top: 1rem;
318
+ padding-top: 1rem;
319
+ border-top: 1px solid var(--gray-200);
320
  }
321
 
322
  .card-metric {
323
  text-align: center;
324
+ flex: 1;
325
+ padding: 0.5rem;
326
+ border-radius: 8px;
327
+ background-color: var(--gray-100);
328
+ margin: 0 0.3rem;
329
  }
330
 
331
  .card-metric-value {
332
+ font-weight: 700;
333
  font-size: 1.5rem;
334
  }
335
 
336
  .card-metric-label {
337
+ font-size: 0.85rem;
338
+ color: var(--gray-600);
339
+ margin-top: 0.3rem;
340
  }
341
  </style>
342
  """, unsafe_allow_html=True)
 
357
  from modules.achievements.achievements_app import AchievementsApp
358
  from modules.ai_finetuning.finetuning_app import FinetuningApp
359
  from modules.document_comparison.comparison_app import DocumentComparisonApp
360
+ from modules.document_analysis.document_analysis_app import DocumentAnalysisApp
361
 
362
  # إنشاء مجلدات البيانات الضرورية
363
  create_directory_if_not_exists(get_data_folder())
 
393
  resources_app.render()
394
 
395
  elif selected_module == "تحليل المستندات":
396
+ # استخدام فئة تحليل المستندات الكاملة
397
+ document_analysis_app = DocumentAnalysisApp()
398
+ document_analysis_app.render()
399
 
400
  elif selected_module == "مقارنة المستندات":
401
  # تقديم واجهة مقارنة المستندات
 
495
  with col1:
496
  st.markdown("""
497
  <div class="indicator">
498
+ <div class="indicator-value">24</div>
499
  <div class="indicator-label">المناقصات النشطة</div>
500
+ <div style="font-size: 1.1rem; margin-top: 5px;">
501
+ <i class="fas fa-arrow-up" style="color: var(--success-color);"></i>
502
+ <span style="color: var(--success-color); font-weight: 600;">+3</span> هذا الشهر
503
+ </div>
504
  </div>
505
  """, unsafe_allow_html=True)
506
 
507
  with col2:
508
  st.markdown("""
509
  <div class="indicator">
510
+ <div class="indicator-value">8</div>
511
  <div class="indicator-label">مشاريع قيد التنفيذ</div>
512
+ <div style="font-size: 1.1rem; margin-top: 5px;">
513
+ <i class="fas fa-arrow-up" style="color: var(--success-color);"></i>
514
+ <span style="color: var(--success-color); font-weight: 600;">+2</span> هذا الشهر
515
+ </div>
516
  </div>
517
  """, unsafe_allow_html=True)
518
 
519
  with col3:
520
  st.markdown("""
521
  <div class="indicator">
522
+ <div class="indicator-value">12</div>
523
  <div class="indicator-label">مستندات قيد التحليل</div>
524
+ <div style="font-size: 1.1rem; margin-top: 5px;">
525
+ <i class="fas fa-check-circle" style="color: var(--primary-color);"></i>
526
+ <span style="color: var(--primary-color); font-weight: 600;">65%</span> مكتمل
527
+ </div>
528
  </div>
529
  """, unsafe_allow_html=True)
530
 
531
  with col4:
532
  st.markdown("""
533
  <div class="indicator">
534
+ <div class="indicator-value">5</div>
535
  <div class="indicator-label">تنبيهات تتطلب الاهتمام</div>
536
+ <div style="font-size: 1.1rem; margin-top: 5px;">
537
+ <i class="fas fa-arrow-down" style="color: var(--success-color);"></i>
538
+ <span style="color: var(--success-color); font-weight: 600;">-2</span> آخر أسبوع
539
+ </div>
540
  </div>
541
  """, unsafe_allow_html=True)
542
 
 
615
  st.markdown("### الوصول السريع")
616
 
617
  st.markdown("""
618
+ <div class="quick-actions">
619
+ <a href="#" class="quick-action-button" style="background: linear-gradient(135deg, #0B6E4F 0%, #08875D 100%);">
620
+ <i class="fas fa-file-alt"></i>
621
+ <span>تحليل مستند جديد</span>
622
+ </a>
623
+
624
+ <a href="#" class="quick-action-button" style="background: linear-gradient(135deg, #38b000 0%, #008000 100%);">
625
+ <i class="fas fa-calculator"></i>
626
+ <span>حساب تكاليف مشروع</span>
627
+ </a>
628
+
629
+ <a href="#" class="quick-action-button" style="background: linear-gradient(135deg, #ff9500 0%, #ff7000 100%);">
630
+ <i class="fas fa-exclamation-triangle"></i>
631
+ <span>تقييم مخاطر العقد</span>
632
+ </a>
633
+
634
+ <a href="#" class="quick-action-button" style="background: linear-gradient(135deg, #9d4edd 0%, #7b2cbf 100%);">
635
+ <i class="fas fa-map-marker-alt"></i>
636
+ <span>استعراض خريطة المشاريع</span>
637
+ </a>
638
+
639
+ <a href="#" class="quick-action-button" style="background: linear-gradient(135deg, #3a86ff 0%, #0077b6 100%);">
640
+ <i class="fas fa-chart-bar"></i>
641
+ <span>إنشاء تقارير تحليلية</span>
642
+ </a>
643
  </div>
644
+
645
+ <style>
646
+ .quick-actions {
647
+ display: grid;
648
+ gap: 12px;
649
+ }
650
+
651
+ .quick-action-button {
652
+ display: flex;
653
+ align-items: center;
654
+ justify-content: flex-end;
655
+ color: white;
656
+ border: none;
657
+ border-radius: 8px;
658
+ padding: 14px 16px;
659
+ text-align: right;
660
+ cursor: pointer;
661
+ font-weight: 600;
662
+ text-decoration: none;
663
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
664
+ transition: all 0.3s ease;
665
+ }
666
+
667
+ .quick-action-button:hover {
668
+ transform: translateY(-3px);
669
+ box-shadow: 0 6px 12px rgba(0, 0, 0, 0.15);
670
+ }
671
+
672
+ .quick-action-button i {
673
+ margin-left: 12px;
674
+ font-size: 1.2rem;
675
+ width: 24px;
676
+ text-align: center;
677
+ }
678
+ </style>
679
  """, unsafe_allow_html=True)
680
 
681
  st.markdown("### آخر التنبيهات")
682
 
683
  st.markdown("""
684
+ <div class="alerts-container">
685
+ <div class="alert alert-danger">
686
+ <div class="alert-icon">
687
+ <i class="fas fa-exclamation-circle"></i>
688
+ </div>
689
+ <div class="alert-content">
690
+ <div class="alert-title">انتهاء موعد تقديم المناقصة</div>
691
+ <div class="alert-message">مشروع إنشاء الطريق السريع - متبقي 3 أيام</div>
692
+ <div class="alert-time">منذ 2 ساعة</div>
693
+ </div>
694
+ </div>
695
+
696
+ <div class="alert alert-warning">
697
+ <div class="alert-icon">
698
+ <i class="fas fa-bell"></i>
699
+ </div>
700
+ <div class="alert-content">
701
+ <div class="alert-title">تغيير في شروط المناقصة</div>
702
+ <div class="alert-message">تم تحديث مستندات مشروع شبكة الصرف الصحي</div>
703
+ <div class="alert-time">منذ 5 ساعات</div>
704
+ </div>
705
+ </div>
706
+
707
+ <div class="alert alert-success">
708
+ <div class="alert-icon">
709
+ <i class="fas fa-check-circle"></i>
710
+ </div>
711
+ <div class="alert-content">
712
+ <div class="alert-title">إكمال تحليل المستند</div>
713
+ <div class="alert-message">اكتمل تحليل عقد بناء المدارس بنجاح</div>
714
+ <div class="alert-time">منذ يوم واحد</div>
715
+ </div>
716
+ </div>
717
  </div>
718
 
719
+ <style>
720
+ .alerts-container {
721
+ display: flex;
722
+ flex-direction: column;
723
+ gap: 12px;
724
+ }
725
+
726
+ .alert {
727
+ display: flex;
728
+ align-items: center;
729
+ border-radius: 8px;
730
+ padding: 12px;
731
+ transition: all 0.3s ease;
732
+ box-shadow: 0 2px 5px rgba(0, 0, 0, 0.05);
733
+ }
734
+
735
+ .alert:hover {
736
+ transform: translateY(-2px);
737
+ box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
738
+ }
739
+
740
+ .alert-danger {
741
+ background-color: #FFF5F5;
742
+ border-right: 4px solid var(--danger-color);
743
+ }
744
+
745
+ .alert-warning {
746
+ background-color: #FFFBEB;
747
+ border-right: 4px solid var(--warning-color);
748
+ }
749
+
750
+ .alert-success {
751
+ background-color: #F0FDF4;
752
+ border-right: 4px solid var(--success-color);
753
+ }
754
+
755
+ .alert-icon {
756
+ margin-left: 14px;
757
+ font-size: 1.4rem;
758
+ width: 40px;
759
+ height: 40px;
760
+ display: flex;
761
+ align-items: center;
762
+ justify-content: center;
763
+ border-radius: 50%;
764
+ }
765
+
766
+ .alert-danger .alert-icon {
767
+ color: var(--danger-color);
768
+ background-color: rgba(239, 68, 68, 0.1);
769
+ }
770
+
771
+ .alert-warning .alert-icon {
772
+ color: var(--warning-color);
773
+ background-color: rgba(245, 158, 11, 0.1);
774
+ }
775
+
776
+ .alert-success .alert-icon {
777
+ color: var(--success-color);
778
+ background-color: rgba(16, 185, 129, 0.1);
779
+ }
780
+
781
+ .alert-content {
782
+ flex: 1;
783
+ }
784
+
785
+ .alert-title {
786
+ font-weight: 700;
787
+ font-size: 1rem;
788
+ margin-bottom: 4px;
789
+ }
790
+
791
+ .alert-danger .alert-title {
792
+ color: var(--danger-color);
793
+ }
794
+
795
+ .alert-warning .alert-title {
796
+ color: var(--warning-color);
797
+ }
798
+
799
+ .alert-success .alert-title {
800
+ color: var(--success-color);
801
+ }
802
+
803
+ .alert-message {
804
+ font-size: 0.9rem;
805
+ color: var(--gray-700);
806
+ }
807
+
808
+ .alert-time {
809
+ font-size: 0.75rem;
810
+ color: var(--gray-500);
811
+ margin-top: 4px;
812
+ }
813
+ </style>
814
  """, unsafe_allow_html=True)
815
 
816
  # معلومات حول النظام
 
832
  """, unsafe_allow_html=True)
833
 
834
 
835
+ # تم حذف دالة render_document_analysis() لأن الوظيفة أصبحت منفذة عبر كلاس DocumentAnalysisApp
836
+
837
+ # التحليلات الأخيرة
838
+ st.markdown("### التحليلات الأخيرة")
839
 
840
  st.markdown("""
841
+ <div class="table-responsive">
842
+ <table class="modern-table">
843
+ <thead>
844
+ <tr>
845
+ <th>اسم المستند</th>
846
+ <th>نوع التحليل</th>
847
+ <th>تاريخ التحليل</th>
848
+ <th>الحالة</th>
849
+ <th>الإجراءات</th>
850
+ </tr>
851
+ </thead>
852
+ <tbody>
853
+ <tr>
854
+ <td>
855
+ <div class="document-item">
856
+ <div class="document-icon pdf-icon">
857
+ <i class="fas fa-file-pdf"></i>
858
+ </div>
859
+ <div class="document-info">
860
+ <div class="document-title">عقد إنشاء طريق سريع</div>
861
+ <div class="document-meta">PDF، 2.4 MB</div>
862
+ </div>
863
+ </div>
864
+ </td>
865
+ <td>تحليل شامل</td>
866
+ <td>2025-03-25</td>
867
+ <td><span class="status-badge status-completed">مكتمل</span></td>
868
+ <td>
869
+ <div class="action-buttons">
870
+ <button class="action-btn view-btn">
871
+ <i class="fas fa-eye"></i>
872
+ <span>عرض</span>
873
+ </button>
874
+ <button class="action-btn download-btn">
875
+ <i class="fas fa-download"></i>
876
+ <span>تنزيل</span>
877
+ </button>
878
+ </div>
879
+ </td>
880
+ </tr>
881
+ <tr>
882
+ <td>
883
+ <div class="document-item">
884
+ <div class="document-icon excel-icon">
885
+ <i class="fas fa-file-excel"></i>
886
+ </div>
887
+ <div class="document-info">
888
+ <div class="document-title">جداول كميات مشروع صرف صحي</div>
889
+ <div class="document-meta">XLSX، 1.7 MB</div>
890
+ </div>
891
+ </div>
892
+ </td>
893
+ <td>تحليل جداول الكميات</td>
894
+ <td>2025-03-23</td>
895
+ <td><span class="status-badge status-completed">مكتمل</span></td>
896
+ <td>
897
+ <div class="action-buttons">
898
+ <button class="action-btn view-btn">
899
+ <i class="fas fa-eye"></i>
900
+ <span>عرض</span>
901
+ </button>
902
+ <button class="action-btn download-btn">
903
+ <i class="fas fa-download"></i>
904
+ <span>تنزيل</span>
905
+ </button>
906
+ </div>
907
+ </td>
908
+ </tr>
909
+ <tr>
910
+ <td>
911
+ <div class="document-item">
912
+ <div class="document-icon pdf-icon">
913
+ <i class="fas fa-file-pdf"></i>
914
+ </div>
915
+ <div class="document-info">
916
+ <div class="document-title">شروط وأحكام عقد بناء مدارس</div>
917
+ <div class="document-meta">PDF، 1.1 MB</div>
918
+ </div>
919
+ </div>
920
+ </td>
921
+ <td>تحليل الشروط والأحكام</td>
922
+ <td>2025-03-20</td>
923
+ <td><span class="status-badge status-completed">مكتمل</span></td>
924
+ <td>
925
+ <div class="action-buttons">
926
+ <button class="action-btn view-btn">
927
+ <i class="fas fa-eye"></i>
928
+ <span>عرض</span>
929
+ </button>
930
+ <button class="action-btn download-btn">
931
+ <i class="fas fa-download"></i>
932
+ <span>تنزيل</span>
933
+ </button>
934
+ </div>
935
+ </td>
936
+ </tr>
937
+ <tr>
938
+ <td>
939
+ <div class="document-item">
940
+ <div class="document-icon pdf-icon">
941
+ <i class="fas fa-file-pdf"></i>
942
+ </div>
943
+ <div class="document-info">
944
+ <div class="document-title">ملحق عقد مشروع كباري</div>
945
+ <div class="document-meta">PDF، 890 KB</div>
946
+ </div>
947
+ </div>
948
+ </td>
949
+ <td>تحليل شامل</td>
950
+ <td>2025-03-18</td>
951
+ <td><span class="status-badge status-processing">قيد المعالجة</span></td>
952
+ <td>
953
+ <div class="action-buttons">
954
+ <button class="action-btn view-btn disabled">
955
+ <i class="fas fa-eye"></i>
956
+ <span>عرض</span>
957
+ </button>
958
+ <button class="action-btn download-btn disabled">
959
+ <i class="fas fa-download"></i>
960
+ <span>تنزيل</span>
961
+ </button>
962
+ </div>
963
+ </td>
964
+ </tr>
965
+ </tbody>
966
+ </table>
967
  </div>
 
 
 
 
968
 
969
+ <style>
970
+ .table-responsive {
971
+ overflow-x: auto;
972
+ margin-bottom: 1.5rem;
973
+ border-radius: var(--border-radius);
974
+ box-shadow: var(--shadow-sm);
975
+ }
 
 
976
 
977
+ .modern-table {
978
+ width: 100%;
979
+ border-collapse: separate;
980
+ border-spacing: 0;
981
+ background-color: white;
982
+ border-radius: var(--border-radius);
983
+ overflow: hidden;
984
+ }
 
 
 
 
 
985
 
986
+ .modern-table th {
987
+ background-color: var(--primary-color);
988
+ color: white;
989
+ padding: 12px 16px;
990
+ text-align: right;
991
+ font-weight: var(--font-weight-semibold);
992
+ border: none;
993
+ }
 
 
 
 
 
994
 
995
+ .modern-table td {
996
+ padding: 12px 16px;
997
+ text-align: right;
998
+ border-bottom: 1px solid var(--gray-200);
999
+ vertical-align: middle;
1000
+ }
1001
+
1002
+ .modern-table tr:last-child td {
1003
+ border-bottom: none;
1004
+ }
1005
+
1006
+ .modern-table tr:nth-child(even) {
1007
+ background-color: var(--gray-50);
1008
+ }
1009
+
1010
+ .modern-table tr:hover {
1011
+ background-color: var(--gray-100);
1012
+ }
1013
+
1014
+ .document-item {
1015
+ display: flex;
1016
+ align-items: center;
1017
+ }
1018
+
1019
+ .document-icon {
1020
+ width: 40px;
1021
+ height: 40px;
1022
+ border-radius: var(--border-radius-sm);
1023
+ display: flex;
1024
+ align-items: center;
1025
+ justify-content: center;
1026
+ margin-left: 12px;
1027
+ color: white;
1028
+ font-size: 18px;
1029
+ }
1030
+
1031
+ .pdf-icon {
1032
+ background-color: #f44336;
1033
+ }
1034
+
1035
+ .excel-icon {
1036
+ background-color: #4caf50;
1037
+ }
1038
+
1039
+ .document-info {
1040
+ display: flex;
1041
+ flex-direction: column;
1042
+ }
1043
+
1044
+ .document-title {
1045
+ font-weight: var(--font-weight-medium);
1046
+ color: var(--gray-800);
1047
+ margin-bottom: 4px;
1048
+ }
1049
+
1050
+ .document-meta {
1051
+ font-size: var(--font-size-xs);
1052
+ color: var(--gray-500);
1053
+ }
1054
+
1055
+ .status-badge {
1056
+ display: inline-flex;
1057
+ align-items: center;
1058
+ justify-content: center;
1059
+ padding: 4px 12px;
1060
+ border-radius: 50px;
1061
+ font-size: var(--font-size-xs);
1062
+ font-weight: var(--font-weight-medium);
1063
+ }
1064
+
1065
+ .status-completed {
1066
+ background-color: var(--success-light);
1067
+ color: var(--success-color);
1068
+ }
1069
+
1070
+ .status-processing {
1071
+ background-color: var(--warning-light);
1072
+ color: var(--warning-color);
1073
+ }
1074
+
1075
+ .status-failed {
1076
+ background-color: var(--danger-light);
1077
+ color: var(--danger-color);
1078
+ }
1079
+
1080
+ .action-buttons {
1081
+ display: flex;
1082
+ gap: 8px;
1083
+ }
1084
+
1085
+ .action-btn {
1086
+ display: inline-flex;
1087
+ align-items: center;
1088
+ padding: 6px 12px;
1089
+ border-radius: var(--border-radius-sm);
1090
+ border: none;
1091
+ font-size: var(--font-size-xs);
1092
+ font-weight: var(--font-weight-medium);
1093
+ cursor: pointer;
1094
+ transition: all 0.2s ease;
1095
+ }
1096
+
1097
+ .action-btn i {
1098
+ margin-left: 6px;
1099
+ }
1100
+
1101
+ .view-btn {
1102
+ background-color: var(--primary-light);
1103
+ color: var(--primary-dark);
1104
+ }
1105
+
1106
+ .view-btn:hover {
1107
+ background-color: var(--primary-color);
1108
+ color: white;
1109
+ }
1110
+
1111
+ .download-btn {
1112
+ background-color: var(--gray-200);
1113
+ color: var(--gray-700);
1114
+ }
1115
+
1116
+ .download-btn:hover {
1117
+ background-color: var(--gray-300);
1118
+ }
1119
+
1120
+ .action-btn.disabled {
1121
+ background-color: var(--gray-200);
1122
+ color: var(--gray-400);
1123
+ cursor: not-allowed;
1124
+ opacity: 0.7;
1125
+ }
1126
+
1127
+ .action-btn.disabled:hover {
1128
+ background-color: var(--gray-200);
1129
+ color: var(--gray-400);
1130
+ }
1131
+ </style>
1132
  """, unsafe_allow_html=True)
1133
 
1134
  # إحصائيات التحليل
 
1138
 
1139
  with col1:
1140
  st.markdown("""
1141
+ <div class="stats-card">
1142
+ <div class="stats-header">
1143
+ <h4>توزيع أنواع المستندات</h4>
 
 
 
 
 
 
 
1144
  </div>
1145
 
1146
+ <div class="stats-content">
1147
+ <div class="chart-item">
1148
+ <div class="chart-item-header">
1149
+ <div class="chart-label">
1150
+ <div class="color-dot" style="background-color: var(--primary-color);"></div>
1151
+ <span>عقود ومناقصات</span>
1152
+ </div>
1153
+ <div class="chart-value">45%</div>
1154
+ </div>
1155
+ <div class="progress-bar-container">
1156
+ <div class="progress-bar" style="width: 45%; background: var(--primary-gradient);"></div>
1157
+ </div>
1158
  </div>
1159
+
1160
+ <div class="chart-item">
1161
+ <div class="chart-item-header">
1162
+ <div class="chart-label">
1163
+ <div class="color-dot" style="background-color: var(--success-color);"></div>
1164
+ <span>جداول كميات</span>
1165
+ </div>
1166
+ <div class="chart-value">30%</div>
1167
+ </div>
1168
+ <div class="progress-bar-container">
1169
+ <div class="progress-bar" style="width: 30%; background: var(--success-gradient);"></div>
1170
+ </div>
1171
  </div>
1172
+
1173
+ <div class="chart-item">
1174
+ <div class="chart-item-header">
1175
+ <div class="chart-label">
1176
+ <div class="color-dot" style="background-color: var(--warning-color);"></div>
1177
+ <span>شروط وأحكام</span>
1178
+ </div>
1179
+ <div class="chart-value">15%</div>
1180
+ </div>
1181
+ <div class="progress-bar-container">
1182
+ <div class="progress-bar" style="width: 15%; background: var(--warning-gradient);"></div>
1183
+ </div>
 
 
 
 
1184
  </div>
1185
+
1186
+ <div class="chart-item">
1187
+ <div class="chart-item-header">
1188
+ <div class="chart-label">
1189
+ <div class="color-dot" style="background-color: var(--gray-500);"></div>
1190
+ <span>مستندات أخرى</span>
1191
+ </div>
1192
+ <div class="chart-value">10%</div>
1193
+ </div>
1194
+ <div class="progress-bar-container">
1195
+ <div class="progress-bar" style="width: 10%; background: linear-gradient(135deg, var(--gray-500) 0%, var(--gray-600) 100%);"></div>
1196
+ </div>
1197
  </div>
1198
  </div>
1199
  </div>
 
1201
 
1202
  with col2:
1203
  st.markdown("""
1204
+ <div class="stats-card">
1205
+ <div class="stats-header">
1206
+ <h4>إحصائيات التحليل الشهرية</h4>
1207
+ </div>
1208
+
1209
+ <div class="counters-container">
1210
+ <div class="counter-item">
1211
+ <div class="counter-value primary">42</div>
1212
+ <div class="counter-label">مستند تم تحليله</div>
1213
  </div>
1214
+ <div class="counter-item">
1215
+ <div class="counter-value success">38</div>
1216
+ <div class="counter-label">تحليل ناجح</div>
1217
  </div>
1218
+ <div class="counter-item">
1219
+ <div class="counter-value warning">4</div>
1220
+ <div class="counter-label">تحليل غير مكتمل</div>
1221
  </div>
1222
  </div>
1223
 
1224
+ <div class="stats-subheader">
1225
+ <h4>متوسط وقت المعالجة</h4>
 
 
 
 
 
1226
  </div>
1227
 
1228
+ <div class="stats-content">
1229
+ <div class="chart-item">
1230
+ <div class="chart-item-header">
1231
+ <div class="chart-label">
1232
+ <span>تحليل شامل</span>
1233
+ </div>
1234
+ <div class="chart-value time">2:30</div>
1235
+ </div>
1236
+ <div class="progress-bar-container">
1237
+ <div class="progress-bar" style="width: 80%; background: var(--primary-gradient);"></div>
1238
+ </div>
1239
  </div>
1240
+
1241
+ <div class="chart-item">
1242
+ <div class="chart-item-header">
1243
+ <div class="chart-label">
1244
+ <span>جداول الكميات</span>
1245
+ </div>
1246
+ <div class="chart-value time">1:45</div>
1247
+ </div>
1248
+ <div class="progress-bar-container">
1249
+ <div class="progress-bar" style="width: 50%; background: var(--success-gradient);"></div>
1250
+ </div>
1251
+ </div>
1252
+
1253
+ <div class="chart-item">
1254
+ <div class="chart-item-header">
1255
+ <div class="chart-label">
1256
+ <span>الشروط والأحكام</span>
1257
+ </div>
1258
+ <div class="chart-value time">2:00</div>
1259
+ </div>
1260
+ <div class="progress-bar-container">
1261
+ <div class="progress-bar" style="width: 60%; background: var(--warning-gradient);"></div>
1262
+ </div>
1263
  </div>
 
1264
  </div>
1265
  </div>
1266
+
1267
+ <style>
1268
+ .stats-card {
1269
+ background-color: white;
1270
+ border-radius: var(--border-radius);
1271
+ padding: var(--spacing-lg);
1272
+ box-shadow: var(--shadow-card);
1273
+ height: 100%;
1274
+ }
1275
+
1276
+ .stats-header h4, .stats-subheader h4 {
1277
+ color: var(--primary-color);
1278
+ font-size: var(--font-size-lg);
1279
+ font-weight: var(--font-weight-semibold);
1280
+ margin-bottom: var(--spacing-md);
1281
+ padding-bottom: var(--spacing-sm);
1282
+ border-bottom: 1px solid var(--gray-200);
1283
+ }
1284
+
1285
+ .stats-subheader h4 {
1286
+ margin-top: var(--spacing-lg);
1287
+ font-size: var(--font-size-md);
1288
+ }
1289
+
1290
+ .stats-content {
1291
+ display: flex;
1292
+ flex-direction: column;
1293
+ gap: var(--spacing-md);
1294
+ }
1295
+
1296
+ .chart-item {
1297
+ margin-bottom: var(--spacing-sm);
1298
+ }
1299
+
1300
+ .chart-item-header {
1301
+ display: flex;
1302
+ justify-content: space-between;
1303
+ align-items: center;
1304
+ margin-bottom: var(--spacing-xs);
1305
+ }
1306
+
1307
+ .chart-label {
1308
+ display: flex;
1309
+ align-items: center;
1310
+ color: var(--gray-700);
1311
+ font-size: var(--font-size-sm);
1312
+ }
1313
+
1314
+ .color-dot {
1315
+ width: 10px;
1316
+ height: 10px;
1317
+ border-radius: 50%;
1318
+ margin-left: var(--spacing-xs);
1319
+ }
1320
+
1321
+ .chart-value {
1322
+ font-weight: var(--font-weight-semibold);
1323
+ color: var(--gray-800);
1324
+ }
1325
+
1326
+ .chart-value.time {
1327
+ font-family: monospace;
1328
+ font-size: var(--font-size-sm);
1329
+ background-color: var(--gray-100);
1330
+ padding: 2px 6px;
1331
+ border-radius: var(--border-radius-sm);
1332
+ }
1333
+
1334
+ .progress-bar-container {
1335
+ height: 8px;
1336
+ background-color: var(--gray-200);
1337
+ border-radius: 10px;
1338
+ overflow: hidden;
1339
+ }
1340
+
1341
+ .progress-bar {
1342
+ height: 100%;
1343
+ border-radius: 10px;
1344
+ transition: width 0.3s ease;
1345
+ }
1346
+
1347
+ .counters-container {
1348
+ display: flex;
1349
+ justify-content: space-between;
1350
+ text-align: center;
1351
+ margin-bottom: var(--spacing-lg);
1352
+ }
1353
+
1354
+ .counter-item {
1355
+ display: flex;
1356
+ flex-direction: column;
1357
+ align-items: center;
1358
+ }
1359
+
1360
+ .counter-value {
1361
+ font-size: var(--font-size-3xl);
1362
+ font-weight: var(--font-weight-bold);
1363
+ margin-bottom: var(--spacing-xs);
1364
+ }
1365
+
1366
+ .counter-value.primary {
1367
+ color: var(--primary-color);
1368
+ }
1369
+
1370
+ .counter-value.success {
1371
+ color: var(--success-color);
1372
+ }
1373
+
1374
+ .counter-value.warning {
1375
+ color: var(--warning-color);
1376
+ }
1377
+
1378
+ .counter-value.danger {
1379
+ color: var(--danger-color);
1380
+ }
1381
+
1382
+ .counter-label {
1383
+ font-size: var(--font-size-xs);
1384
+ color: var(--gray-600);
1385
+ }
1386
+ </style>
1387
  """, unsafe_allow_html=True)
1388
 
1389
 
modules/ai_assistant/__init__.py CHANGED
@@ -1,5 +1 @@
1
- """
2
- وحدة المساعد الذكي
3
- """
4
-
5
- __version__ = '1.0.0'
 
1
+ # تهيئة حزمة المساعد الذكي
 
 
 
 
modules/ai_assistant/ai_assistant.py CHANGED
@@ -2,765 +2,401 @@
2
  # -*- coding: utf-8 -*-
3
 
4
  """
5
- وحدة المساعد الذكي التفاعلية
6
- تتيح للمستخدمين التفاعل مع نماذج الذكاء الاصطناعي المتقدمة للحصول على مساعدة في تحليل العقود والمناقصات
7
  """
8
 
9
  import os
10
  import sys
11
  import json
12
- import re
13
  import time
14
- import base64
15
- import tempfile
16
  import logging
17
  from datetime import datetime
 
 
 
18
  import streamlit as st
19
  import pandas as pd
20
  import numpy as np
21
- import requests
22
- from io import BytesIO
23
- from PIL import Image
24
- import openai
25
- import plotly.express as px
26
- import plotly.graph_objects as go
 
 
 
 
 
 
 
 
 
 
 
27
 
28
  # إضافة مسار النظام للوصول للملفات المشتركة
29
  sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "../..")))
30
 
31
- # استيراد المكونات المساعدة
32
- from utils.helpers import create_directory_if_not_exists, format_time, get_user_info, render_credits, load_css
33
-
34
 
35
  class AIAssistant:
36
- """فئة المساعد الذكي التفاعلية"""
37
 
38
  def __init__(self):
39
  """تهيئة المساعد الذكي"""
40
- self.conversations_dir = os.path.join(os.path.dirname(__file__), '..', '..', 'data', 'assistant_conversations')
41
- create_directory_if_not_exists(self.conversations_dir)
42
-
43
- # تهيئة مفتاح OpenAI API
44
- self.openai_api_key = os.environ.get("OPENAI_API_KEY")
45
- if self.openai_api_key:
46
- openai.api_key = self.openai_api_key
47
- self.is_api_available = True
48
- else:
49
- self.is_api_available = False
50
-
51
- # نموذج OpenAI المستخدم
52
- self.model = "gpt-4o" # النموذج الأحدث من OpenAI
53
-
54
- # تهيئة حالة المحادثة في الجلسة
55
- if "assistant_messages" not in st.session_state:
56
- st.session_state.assistant_messages = []
57
-
58
- if "assistant_mode" not in st.session_state:
59
- st.session_state.assistant_mode = "general"
60
-
61
- if "document_context" not in st.session_state:
62
- st.session_state.document_context = None
63
-
64
- # الأنماط المتاحة للمساعد
65
- self.assistant_modes = {
66
- "general": "مساعد عام",
67
- "contract_analysis": "تحليل العقود",
68
- "cost_estimation": "تقدير التكاليف",
69
- "risk_assessment": "تقييم المخاطر",
70
- "project_planning": "تخطيط المشاريع"
71
- }
72
-
73
- # توجيهات النظام للمساعد
74
- self.system_prompts = {
75
- "general": """
76
- أنت مساعد ذكي متخصص في شركة شبه الجزيرة للمقاولات، وتعمل ضمن نظام WAHBi لتحليل العقود والمناقصات.
77
- دورك هو مساعدة المستخدمين في:
78
- 1. تحليل المستندات والعقود، وتوضيح بنود العقود وفهم الالتزامات والشروط.
79
- 2. المساعدة في تسعير المشاريع وحساب التكاليف والموارد.
80
- 3. تقييم مخاطر العقود والمشاريع والمساعدة في اتخاذ القرارات.
81
- 4. المساعدة في إدارة المشاريع ومتابعة الإنجاز.
82
-
83
- استخدم لغة مهنية واضحة ومباشرة. قدم إجابات دقيقة ومختصرة.
84
- عند قيام المستخدم بسؤال عن كيفية استخدام النظام، قم بإرشاده إلى الوحدة المناسبة في النظام.
85
-
86
- معلومات هامة عن وحدات النظام:
87
- - وحدة تحليل المستندات: لتحليل العقود والمناقصات باستخدام الذكاء الاصطناعي.
88
- - وحدة مقارنة المستندات: لمقارنة نسخ مختلفة من المستندات وتحديد التغييرات.
89
- - وحدة التسعير المتكاملة: لحساب تكاليف المشاريع بن��ءً على الموارد والمواد والعمالة.
90
- - وحدة تقييم مخاطر العقود: لتحليل وتقييم المخاطر المحتملة في العقود والمشاريع.
91
- - وحدة متتبع حالة المشروع: لمتابعة تقدم المشاريع وعرض مؤشرات الأداء.
92
- - وحدة خريطة المشاريع: لعرض مواقع المشاريع على الخريطة بشكل تفاعلي.
93
- - وحدة الإشعارات الذكية: لإرسال تنبيهات وإشعارات للمستخدمين حول المشاريع.
94
-
95
- تذكر أن تكون مفيداً ودقيقاً ومهنياً في جميع إجاباتك.
96
- """,
97
-
98
- "contract_analysis": """
99
- أنت محلل عقود متخصص في تحليل العقود والمناقصات لشركات المقاولات.
100
- مهمتك هي تحليل العقود وتحديد:
101
- - الالتزامات الرئيسية
102
- - المواعيد النهائية والتسليمات
103
- - الشروط الجزائية والغرامات
104
- - آلية الدفع والمستحقات المالية
105
- - الشروط الخاصة والاستثناءات
106
- - المخاطر المحتملة وكيفية التخفيف منها
107
-
108
- عند تحليل عقد، قم بتوضيح البنود غير المواتية التي قد تسبب مشاكل مستقبلية.
109
- استخدم لغة قانونية دقيقة مع شرح المصطلحات القانونية بلغة مبسطة.
110
- قدم توصيات عملية لكيفية التعامل مع بنود العقد وتجنب المخاطر.
111
- """,
112
-
113
- "cost_estimation": """
114
- أنت خبير في تقدير تكاليف مشاريع البناء والمقاولات.
115
- مهمتك هي مساعدة المستخدم في:
116
- - تقدير تكاليف المشاريع بناءً على وصف المشروع ومتطلباته
117
- - حساب تكاليف المواد والعمالة والمعدات والنفقات العامة
118
- - توضيح كيفية تخصيص الميزانية بين مختلف عناصر المشروع
119
- - تحديد التكاليف غير المباشرة التي قد يغفل عنها المستخدم
120
- - اقتراح طرق لتقليل التكاليف دون التأثير على جودة المشروع
121
-
122
- استخدم أسلوب منهجي في تقدير التكاليف واشرح افتراضاتك بوضوح.
123
- قدم نطاقات تقديرية بدلاً من أرقام دقيقة للتكاليف حيثما كان ذلك مناسباً.
124
- عند الإشارة إلى تكاليف، وضح ما إذا كانت التكاليف تشمل ضريبة القيمة المضافة أم لا.
125
- """,
126
-
127
- "risk_assessment": """
128
- أنت خبير في تقييم مخاطر مشاريع البناء والمقاولات.
129
- مهمتك هي مساعدة المستخدم في:
130
- - تحديد المخاطر المحتملة في المشاريع والعقود
131
- - تقييم احتمالية وتأثير كل خطر
132
- - اقتراح استراتيجيات للتخفيف من المخاطر
133
- - تحليل السيناريوهات المحتملة وخطط الطوارئ
134
- - تقديم أفضل الممارسات لإدارة المخاطر في مشاريع المقاولات
135
-
136
- صنف المخاطر إلى فئات (عالية، متوسطة، منخفضة) بناءً على احتماليتها وتأثيرها.
137
- اشرح كيف يمكن للشركة أن تحول بعض المخاطر إلى فرص.
138
- قدم أمثلة عملية من مشاريع مماثلة لتوضيح كيفية إدارة المخاطر المحددة.
139
- """,
140
-
141
- "project_planning": """
142
- أنت خبير في تخطيط وإدارة مشاريع البناء والمقاولات.
143
- مهمتك هي مساعدة المستخدم في:
144
- - تخطيط المشاريع وتقسيمها إلى مراحل ومهام
145
- - تحديد الموارد اللازمة والجداول الزمنية
146
- - إنشاء مخطط جانت وتحديد المسار الحرج
147
- - التخطيط للموارد البشرية والمعدات والمواد
148
- - متابعة تقدم المشروع ومؤشرات الأداء
149
-
150
- قدم نصائح عملية لإدارة المشاريع بكفاءة وتجنب التأخيرات.
151
- اشرح كيفية التعامل مع التغييرات والمطالبات خلال تنفيذ المشروع.
152
- قدم أفضل الممارسات للتواصل مع أصحاب المصلحة وإدارة التوقعات.
153
- """
154
- }
155
 
156
- def _call_openai_api(self, messages, model=None, max_tokens=2000):
157
- """استدعاء OpenAI API للحصول على استجابة"""
158
- if not self.is_api_available:
159
- return {
160
- "choices": [{"message": {"content": "عذراً، مفتاح OpenAI API غير متوفر. يرجى التواصل مع مسؤول النظام."}}]
161
- }
162
-
163
  try:
164
- if model is None:
165
- model = self.model
166
-
167
- response = openai.ChatCompletion.create(
168
- model=model,
169
- messages=messages,
170
- max_tokens=max_tokens,
171
- temperature=0.7,
172
- top_p=0.9,
173
- frequency_penalty=0,
174
- presence_penalty=0
175
- )
176
-
177
- return response
178
  except Exception as e:
179
- logging.error(f"خطأ في استدعاء OpenAI API: {e}")
180
- return {
181
- "choices": [{"message": {"content": f"عذراً، حدث خطأ في الاتصال بـ OpenAI API: {str(e)}"}}]
182
- }
183
 
184
- def _call_backend_api(self, endpoint, data):
185
- """استدعاء واجهة API الخلفية للنظام"""
186
  try:
187
- response = requests.post(
188
- f"http://localhost:5000/api/{endpoint}",
189
- json=data,
190
- timeout=60
191
- )
192
-
193
- if response.status_code == 200:
194
- return response.json()
195
- else:
196
- logging.error(f"خطأ في استدعاء واجهة API الخلفية: {response.status_code} - {response.text}")
197
- return {"error": f"خطأ في استدعاء واجهة API الخلفية: {response.status_code}"}
198
  except Exception as e:
199
- logging.error(f"خطأ في الاتصال بواجهة API الخلفية: {e}")
200
- return {"error": f"خطأ في الاتصال بواجهة API الخلفية: {str(e)}"}
201
 
202
- def _process_user_message(self, user_message, mode=None):
203
- """معالجة رسالة المستخدم والحصول على رد من المساعد الذكي"""
204
- if mode is None:
205
- mode = st.session_state.assistant_mode
206
-
207
- # إنشاء قائمة الرسائل للمحادثة
208
- messages = [
209
- {"role": "system", "content": self.system_prompts[mode]}
210
- ]
211
-
212
- # إضافة سياق المستند إذا كان متاحاً
213
- if st.session_state.document_context:
214
- messages.append({
215
- "role": "system",
216
- "content": f"معلومات سياقية عن المستند: {st.session_state.document_context}"
217
- })
218
-
219
- # إضافة المحادثة السابقة
220
- for msg in st.session_state.assistant_messages:
221
- messages.append({
222
- "role": msg["role"],
223
- "content": msg["content"]
224
- })
225
-
226
- # إضافة رسالة المستخدم الحالية
227
- messages.append({
228
- "role": "user",
229
- "content": user_message
230
- })
231
-
232
- # استدعاء API
233
- response = self._call_openai_api(messages)
234
-
235
- # استخراج الرد
236
- assistant_response = response["choices"][0]["message"]["content"]
237
-
238
- # تحديث سجل المحادثة
239
- st.session_state.assistant_messages.append({"role": "user", "content": user_message})
240
- st.session_state.assistant_messages.append({"role": "assistant", "content": assistant_response})
241
-
242
- return assistant_response
243
-
244
- def _clear_chat(self):
245
- """مسح المحادثة الحالية"""
246
- st.session_state.assistant_messages = []
247
- st.session_state.document_context = None
248
-
249
- def _save_conversation(self):
250
- """حفظ المحادثة الحالية"""
251
- if not st.session_state.assistant_messages:
252
- st.warning("لا توجد محادثة لحفظها.")
253
- return False
254
-
255
- timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
256
- user_info = get_user_info()
257
-
258
- conversation_data = {
259
- "timestamp": timestamp,
260
- "user": user_info["username"],
261
- "mode": st.session_state.assistant_mode,
262
- "messages": st.session_state.assistant_messages,
263
- "document_context": st.session_state.document_context
264
- }
265
-
266
- filename = f"conversation_{user_info['username']}_{timestamp}.json"
267
- file_path = os.path.join(self.conversations_dir, filename)
268
-
269
- try:
270
- with open(file_path, 'w', encoding='utf-8') as f:
271
- json.dump(conversation_data, f, ensure_ascii=False, indent=2)
272
-
273
- return True
274
- except Exception as e:
275
- logging.error(f"خطأ في حفظ المحادثة: {e}")
276
- return False
277
-
278
- def _load_conversation(self, filename):
279
- """تحميل محادثة محفوظة"""
280
- file_path = os.path.join(self.conversations_dir, filename)
281
-
282
  try:
283
- with open(file_path, 'r', encoding='utf-8') as f:
284
- conversation_data = json.load(f)
285
-
286
- st.session_state.assistant_messages = conversation_data["messages"]
287
- st.session_state.assistant_mode = conversation_data["mode"]
288
- st.session_state.document_context = conversation_data.get("document_context")
289
 
290
- return True
291
- except Exception as e:
292
- logging.error(f"خطأ في تحميل المحادثة: {e}")
293
- return False
294
-
295
- def _get_saved_conversations(self):
296
- """الحصول على قائمة المحادثات المحفوظة"""
297
- conversations = []
298
-
299
- try:
300
- for filename in os.listdir(self.conversations_dir):
301
- if filename.endswith(".json") and filename.startswith("conversation_"):
302
- file_path = os.path.join(self.conversations_dir, filename)
303
-
304
- with open(file_path, 'r', encoding='utf-8') as f:
305
- data = json.load(f)
306
-
307
- conversations.append({
308
- "filename": filename,
309
- "timestamp": data.get("timestamp", ""),
310
- "user": data.get("user", ""),
311
- "mode": data.get("mode", "general"),
312
- "message_count": len(data.get("messages", []))
313
- })
314
  except Exception as e:
315
- logging.error(f"خطأ في قراءة المحادثات المحفوظة: {e}")
316
-
317
- # ترتيب المحادثات حسب التاريخ (الأحدث أولاً)
318
- conversations.sort(key=lambda x: x["timestamp"], reverse=True)
319
-
320
- return conversations
321
 
322
- def render_chat_interface(self):
323
- """عرض واجهة المحادثة الرئيسية"""
324
- st.markdown("<h2 class='module-title'>المساعد الذكي</h2>", unsafe_allow_html=True)
325
-
326
- # التحقق من توفر OpenAI API
327
- if not self.is_api_available:
328
- st.warning("⚠️ مفتاح OpenAI API غير متوفر. لن يكون المساعد الذكي قادراً على الرد. يرجى التواصل مع مسؤول النظام.")
329
 
330
- # إضافة CSS
331
  st.markdown("""
332
- <style>
333
- .chat-container {
334
- background-color: #f8f9fa;
335
- border-radius: 10px;
336
- padding: 20px;
337
- margin-bottom: 20px;
338
- max-height: 500px;
339
- overflow-y: auto;
340
- }
341
-
342
- .chat-message {
343
- margin-bottom: 15px;
344
- display: flex;
345
- flex-direction: row;
346
- }
347
-
348
- .user-message {
349
- justify-content: flex-end;
350
- }
351
-
352
- .assistant-message {
353
- justify-content: flex-start;
354
- }
355
-
356
- .message-bubble {
357
- padding: 10px 15px;
358
- border-radius: 15px;
359
- max-width: 75%;
360
- }
361
-
362
- .user-bubble {
363
- background-color: #1E88E5;
364
- color: white;
365
- border-top-left-radius: 15px;
366
- border-top-right-radius: 15px;
367
- border-bottom-left-radius: 15px;
368
- border-bottom-right-radius: 0;
369
- }
370
-
371
- .assistant-bubble {
372
- background-color: #f0f0f0;
373
- color: #333;
374
- border-top-left-radius: 15px;
375
- border-top-right-radius: 15px;
376
- border-bottom-left-radius: 0;
377
- border-bottom-right-radius: 15px;
378
- }
379
-
380
- .message-avatar {
381
- width: 40px;
382
- height: 40px;
383
- border-radius: 50%;
384
- background-color: #ccc;
385
- display: flex;
386
- align-items: center;
387
- justify-content: center;
388
- margin: 0 10px;
389
- font-weight: bold;
390
- color: white;
391
- }
392
-
393
- .user-avatar {
394
- background-color: #78909C;
395
- }
396
-
397
- .assistant-avatar {
398
- background-color: #1E88E5;
399
- }
400
 
401
- .message-content {
402
- white-space: pre-wrap;
403
- }
404
 
405
- .message-time {
406
- font-size: 0.8em;
407
- color: #888;
408
- margin-top: 5px;
409
- text-align: right;
410
- }
411
 
412
- .chat-input {
413
- background-color: #f8f9fa;
414
- border-radius: 10px;
415
- padding: 20px;
416
- }
417
 
418
- .suggestions-container {
419
- display: flex;
420
- flex-wrap: wrap;
421
- gap: 10px;
422
- margin-top: 10px;
423
- }
424
-
425
- .suggestion-chip {
426
- background-color: #e9ecef;
427
- border-radius: 20px;
428
- padding: 5px 15px;
429
- cursor: pointer;
430
- text-align: center;
431
- transition: background-color 0.3s;
432
- }
433
 
434
- .suggestion-chip:hover {
435
- background-color: #dee2e6;
436
- }
437
- </style>
438
- """, unsafe_allow_html=True)
439
 
440
- # عرض أوضاع المساعد
441
- st.markdown("#### اختر وضع المساعد الذكي")
 
 
 
 
442
 
443
- col1, col2, col3, col4, col5 = st.columns(5)
444
 
445
  with col1:
446
- if st.button("مساعد عام", key="mode_general",
447
- help="مساعد عام للإجابة على الأسئلة المتعلقة بالعقود والمناقصات"):
448
- st.session_state.assistant_mode = "general"
 
449
  st.rerun()
450
-
451
  with col2:
452
- if st.button("تحليل العقود", key="mode_contract_analysis",
453
- help="متخصص في تحليل العقود وتحديد البنود والشروط والمخاطر"):
454
- st.session_state.assistant_mode = "contract_analysis"
 
455
  st.rerun()
456
-
457
  with col3:
458
- if st.button("تقدير التكاليف", key="mode_cost_estimation",
459
- help="متخصص في تقدير تكاليف المشاريع والبنود"):
460
- st.session_state.assistant_mode = "cost_estimation"
 
461
  st.rerun()
462
 
463
- with col4:
464
- if st.button("تقييم المخاطر", key="mode_risk_assessment",
465
- help="متخصص في تحديد وتقييم المخاطر المحتملة في المشاريع والعقود"):
466
- st.session_state.assistant_mode = "risk_assessment"
467
- st.rerun()
468
 
469
- with col5:
470
- if st.button("تخطيط المشاريع", key="mode_project_planning",
471
- help="متخصص في تخطيط وإدارة المشاريع وتحديد المراحل والموارد"):
472
- st.session_state.assistant_mode = "project_planning"
473
- st.rerun()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
474
 
475
- st.markdown(f"**الوضع الحالي:** {self.assistant_modes[st.session_state.assistant_mode]}")
476
 
477
- # تحميل سياق من مستند (اختياري)
478
- st.markdown("---")
479
- with st.expander("إضافة سياق من مستند", expanded=False):
480
- context_text = st.text_area(
481
- "نص المستند (اختياري)",
482
- value=st.session_state.document_context if st.session_state.document_context else "",
483
- height=150,
484
- help="أضف نص المستند هنا ليتم استخدامه كسياق للمحادثة"
485
- )
486
 
487
- uploaded_file = st.file_uploader(
488
- "أو قم بتحميل ملف نصي أو PDF",
489
- type=["txt", "pdf"],
490
- help="يمكنك تحميل ملف نصي أو PDF ليتم استخدامه كسياق للمحادثة"
491
- )
 
492
 
493
- doc_col1, doc_col2 = st.columns(2)
 
 
 
 
 
494
 
495
- with doc_col1:
496
- if st.button("إضافة السياق", disabled=not context_text and not uploaded_file):
497
- if uploaded_file:
498
- try:
499
- # قراءة الملف المرفوع
500
- if uploaded_file.name.endswith(".pdf"):
501
- import PyPDF2
502
- reader = PyPDF2.PdfReader(uploaded_file)
503
- context = ""
504
- for page in reader.pages:
505
- context += page.extract_text() + "\n"
506
- else:
507
- context = uploaded_file.read().decode("utf-8")
508
-
509
- st.session_state.document_context = context
510
- st.success("تم إضافة نص المستند كسياق للمحادثة بنجاح.")
511
- except Exception as e:
512
- st.error(f"حدث خطأ أثناء قراءة الملف: {str(e)}")
513
- elif context_text:
514
- st.session_state.document_context = context_text
515
- st.success("تم إضافة نص المستند كسياق للمحادثة بنجاح.")
516
 
517
- with doc_col2:
518
- if st.button("مسح السياق", disabled=not st.session_state.document_context):
519
- st.session_state.document_context = None
520
- st.success("تم مسح سياق المستند بنجاح.")
521
-
522
- # عرض المحادثة
523
- st.markdown("---")
524
- st.markdown("#### المحادثة مع المساعد الذكي")
525
-
526
- # عرض رسائل المحادثة
527
- chat_container = st.container()
528
 
529
- with chat_container:
530
- with st.container():
531
- if not st.session_state.assistant_messages:
532
- st.markdown("""
533
- <div style="text-align: center; padding: 30px; color: #666;">
534
- <p>مرحباً بك في المساعد الذكي!</p>
535
- <p>يمكنك البدء بطرح سؤال أو طلب مساعدة.</p>
536
- </div>
537
- """, unsafe_allow_html=True)
538
- else:
539
- message_html = ""
540
-
541
- for msg in st.session_state.assistant_messages:
542
- if msg["role"] == "user":
543
- message_html += f"""
544
- <div class="chat-message user-message">
545
- <div class="message-bubble user-bubble">
546
- <div class="message-content">{msg["content"]}</div>
547
- </div>
548
- <div class="message-avatar user-avatar">أ</div>
549
- </div>
550
- """
551
- else:
552
- message_html += f"""
553
- <div class="chat-message assistant-message">
554
- <div class="message-avatar assistant-avatar">W</div>
555
- <div class="message-bubble assistant-bubble">
556
- <div class="message-content">{msg["content"]}</div>
557
- </div>
558
- </div>
559
- """
560
-
561
- st.markdown(f"""
562
- <div class="chat-container">
563
- {message_html}
564
- </div>
565
- """, unsafe_allow_html=True)
566
 
567
- # ادخال الرسالة
568
- st.markdown("#### أدخل رسالتك")
569
 
570
- with st.container():
571
- with st.form(key="chat_form"):
572
- user_message = st.text_area("رسالتك", height=100, placeholder="اكتب سؤالك أو طلبك هنا...")
573
-
574
- col1, col2, col3 = st.columns([2, 2, 1])
575
-
576
- with col1:
577
- send_button = st.form_submit_button(
578
- "إرسال",
579
- help="إرسال الرسالة إلى المساعد الذكي"
580
- )
581
 
582
- with col2:
583
- suggested_questions = [
584
- "كيف يمكنني تحليل بنود الدفع في العقد؟",
585
- "ما هي أفضل طريقة لتقدير تكاليف مشروع بناء؟",
586
- "كيف أحدد المخاطر المحتملة في مشروع جديد؟",
587
- "كيف يمكنني إنشاء جدول زمني فعال للمشروع؟",
588
- "ما هي أهم البنود التي يجب الانتباه إليها في عقود المقاولات؟"
589
- ]
590
-
591
- if st.session_state.assistant_mode == "contract_analysis":
592
- suggested_questions = [
593
- "كيف أحدد البنود غير المواتية في العقد؟",
594
- "ما هي العناصر الأساسية التي يجب أن يتضمنها عقد المقاولة؟",
595
- "كيف أتعامل مع بنود الغرامات والتعويضات؟",
596
- "كيف يمكنني التفاوض على تحسين شروط الدفع؟",
597
- "ما هي الفروق الرئيسية بين عقد الثمن الثابت وعقد التكلفة زائد أتعاب؟"
598
- ]
599
- elif st.session_state.assistant_mode == "cost_estimation":
600
- suggested_questions = [
601
- "كيف أقدر تكلفة المواد في مشروع بناء؟",
602
- "ما هي نسبة النفقات العامة المعقولة لمشروع مقاولات؟",
603
- "كيف أحسب تكلفة العمالة بدقة؟",
604
- "ما هي العوامل التي تؤثر على تكلفة المعدات؟",
605
- "كيف أقدر هامش الربح المناسب للمشروع؟"
606
- ]
607
-
608
- selected_question = st.selectbox(
609
- "أو اختر سؤال مقترح",
610
- [""] + suggested_questions,
611
- index=0
612
- )
613
 
614
- with col3:
615
- clear_button = st.form_submit_button(
616
- "مسح المحادثة",
617
- help="مسح جميع الرسائل في المحادثة الحالية"
618
- )
 
 
 
 
 
 
 
 
 
 
 
619
 
620
- if send_button and user_message:
621
- # معالجة رسالة المستخدم
622
- with st.spinner("جاري معالجة الرسالة..."):
623
- self._process_user_message(user_message)
624
- st.rerun()
625
 
626
- if send_button and selected_question and not user_message:
627
- # استخدام السؤال المقترح
628
- with st.spinner("جاري معالجة الرسالة..."):
629
- self._process_user_message(selected_question)
630
- st.rerun()
631
 
632
- if clear_button:
633
- self._clear_chat()
634
- st.rerun()
635
-
636
- # زر لحفظ المحادثة
637
- col1, col2, col3 = st.columns([1, 1, 2])
638
-
639
- with col1:
640
- if st.button("حفظ المحادثة", key="save_conversation", disabled=not st.session_state.assistant_messages):
641
- if self._save_conversation():
642
- st.success("تم حفظ المحادثة بنجاح.")
643
- else:
644
- st.error("حدث خطأ أثناء حفظ المحادثة.")
645
-
646
- with col2:
647
- if st.button("تحميل محادثة سابقة", key="show_load_conversation"):
648
- st.session_state.show_conversations = True
649
- st.rerun()
650
-
651
- # عرض المحادثات المحفوظة
652
- if "show_conversations" in st.session_state and st.session_state.show_conversations:
653
- st.markdown("---")
654
- st.markdown("#### المحادثات المحفوظة")
655
 
656
- conversations = self._get_saved_conversations()
 
 
 
 
 
 
657
 
658
- if not conversations:
659
- st.info("لا توجد محادثات محفوظة.")
660
- else:
661
- # عرض المحادثات في جدول
662
- conversation_data = []
663
- for conv in conversations:
664
- timestamp = datetime.strptime(conv["timestamp"], "%Y%m%d%H%M%S") if conv["timestamp"] else ""
665
- formatted_time = timestamp.strftime("%Y-%m-%d %H:%M:%S") if timestamp else ""
666
-
667
- conversation_data.append({
668
- "التاريخ": formatted_time,
669
- "المستخدم": conv["user"],
670
- "وضع المساعد": self.assistant_modes.get(conv["mode"], "غير معروف"),
671
- "عدد الرسائل": conv["message_count"],
672
- "الملف": conv["filename"]
673
- })
674
-
675
- df = pd.DataFrame(conversation_data)
676
- st.dataframe(df, height=300)
677
-
678
- # اختيار محادثة لتحميلها
679
- selected_filename = st.selectbox(
680
- "اختر محادثة لتحميلها",
681
- options=[""] + [conv["filename"] for conv in conversations],
682
- format_func=lambda x: next((f"{c['user']} - {datetime.strptime(c['timestamp'], '%Y%m%d%H%M%S').strftime('%Y-%m-%d %H:%M:%S')}" for c in conversations if c["filename"] == x), x),
683
- index=0
684
- )
685
-
686
- col1, col2 = st.columns(2)
687
-
688
- with col1:
689
- if st.button("تحميل المحادثة المختارة", disabled=not selected_filename):
690
- if self._load_conversation(selected_filename):
691
- st.success("تم تحميل المحادثة بنجاح.")
692
- st.session_state.show_conversations = False
693
- st.rerun()
694
- else:
695
- st.error("حدث خطأ أثناء تحميل المحادثة.")
696
-
697
- with col2:
698
- if st.button("إلغاء", key="cancel_load_conversation"):
699
- st.session_state.show_conversations = False
700
- st.rerun()
701
-
702
- # عرض المعلومات عن وضع المساعد الحالي
703
- st.markdown("---")
704
- st.markdown(f"#### معلومات عن وضع المساعد: {self.assistant_modes[st.session_state.assistant_mode]}")
705
-
706
- if st.session_state.assistant_mode == "general":
707
- st.markdown("""
708
- المساعد العام يمكنه مساعدتك في مجموعة متنوعة من المهام المتعلقة بالعقود والمناقصات وإدارة المشاريع. يمكنه:
709
- - الإجابة على الأسئلة العامة حول العقود والمناقصات
710
- - توجيهك إلى الوحدات المناسبة في النظام
711
- - تقديم معلومات عامة عن إدارة المشاريع وأفضل الممارسات
712
- - المساعدة في فهم المصطلحات والمفاهيم المتعلقة بمجال المقاولات
713
- """)
714
- elif st.session_state.assistant_mode == "contract_analysis":
715
- st.markdown("""
716
- مساعد تحليل العقود متخصص في:
717
- - تحليل بنود العقود وتوضيح معانيها
718
- - تحديد الالتزامات والحقوق لكل طرف
719
- - تسليط الضوء على البنود غير المواتية أو الغامضة
720
- - تقديم توصيات للتفاوض على تحسين شروط العقد
721
- - مقارنة العقد مع أفضل الممارسات في القطاع
722
- """)
723
- elif st.session_state.assistant_mode == "cost_estimation":
724
- st.markdown("""
725
- مساعد تقدير التكاليف متخصص في:
726
- - حساب تكاليف المشاريع بناءً على المتطلبات والمواصفات
727
- - تقدير تكاليف المواد والعمالة والمعدات
728
- - تحليل التكاليف المباشرة وغير المباشرة
729
- - تقديم نصائح لتقليل التكاليف وزيادة الكفاءة
730
- - تحديد العوامل التي قد تؤثر على التكلفة الإجمالية
731
- """)
732
- elif st.session_state.assistant_mode == "risk_assessment":
733
- st.markdown("""
734
- مساعد تقييم المخاطر متخصص في:
735
- - تحديد المخاطر المحتملة في المشاريع والعقود
736
- - تقييم احتمالية وتأثير كل خطر
737
- - اقتراح استراتيجيات للتخفيف من المخاطر
738
- - إنشاء خطط للطوارئ والاستجابة للمخاطر
739
- - تحليل تأثير المخاطر على الجدول الزمني والتكلفة
740
- """)
741
- elif st.session_state.assistant_mode == "project_planning":
742
- st.markdown("""
743
- مساعد تخطيط المشاريع متخصص في:
744
- - تقسيم المشروع إلى مراحل ومهام وأنشطة
745
- - تحديد الموارد اللازمة لكل نشاط
746
- - إنشاء الجداول الزمنية والمسار الحرج
747
- - التخطيط للموارد البشرية والمعدات والمواد
748
- - مراقبة تقدم المشرو�� وإدارة التغييرات
749
- """)
750
-
751
- # عرض معلومات حقوق الملكية
752
- render_credits()
753
 
754
- def render(self):
755
- """عرض واجهة المساعد الذكي الرئيسية"""
756
- # تحميل CSS المخصص
757
- load_css()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
758
 
759
- # عرض واجهة المحادثة
760
- self.render_chat_interface()
761
 
762
 
763
- # تشغيل التطبيق بشكل مستقل عند استدعاء الملف مباشرة
764
  if __name__ == "__main__":
765
  st.set_page_config(
766
  page_title="المساعد الذكي | WAHBi AI",
@@ -769,5 +405,12 @@ if __name__ == "__main__":
769
  initial_sidebar_state="expanded"
770
  )
771
 
 
 
 
 
 
 
 
772
  assistant = AIAssistant()
773
  assistant.render()
 
2
  # -*- coding: utf-8 -*-
3
 
4
  """
5
+ تطبيق المساعد الذكي لنظام واهبي لتحليل العقود والمناقصات - الوحدة الرئيسية
6
+ AI Assistant Main Module for WAHBI Tender Analysis System
7
  """
8
 
9
  import os
10
  import sys
11
  import json
 
12
  import time
 
 
13
  import logging
14
  from datetime import datetime
15
+ from pathlib import Path
16
+
17
+ # تهيئة مكتبات الواجهة
18
  import streamlit as st
19
  import pandas as pd
20
  import numpy as np
21
+
22
+ # مكتبات ذكاء اصطناعي
23
+ try:
24
+ import openai
25
+ from openai import OpenAI
26
+ openai_available = True
27
+ except ImportError:
28
+ openai_available = False
29
+ logging.warning("لم يتم العثور على مكتبة OpenAI. بعض الوظائف قد لا تعمل.")
30
+
31
+ try:
32
+ import plotly.express as px
33
+ import plotly.graph_objects as go
34
+ plotly_available = True
35
+ except ImportError:
36
+ plotly_available = False
37
+ logging.warning("لم يتم العثور على مكتبة Plotly. بعض الوظائف قد لا تعمل.")
38
 
39
  # إضافة مسار النظام للوصول للملفات المشتركة
40
  sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "../..")))
41
 
 
 
 
42
 
43
  class AIAssistant:
44
+ """فئة المساعد الذكي"""
45
 
46
  def __init__(self):
47
  """تهيئة المساعد الذكي"""
48
+ self.initialize_session_state()
49
+ self.load_conversation_history()
50
+ self.openai_client = self.initialize_openai_client()
51
+
52
+ def initialize_session_state(self):
53
+ """تهيئة متغيرات حالة الجلسة"""
54
+ if 'ai_messages' not in st.session_state:
55
+ st.session_state.ai_messages = []
56
+ if 'waiting_for_answer' not in st.session_state:
57
+ st.session_state.waiting_for_answer = False
58
+ if 'api_key_error' not in st.session_state:
59
+ st.session_state.api_key_error = False
60
+ if 'assistant_context' not in st.session_state:
61
+ st.session_state.assistant_context = "عام" # سياق المحادثة الافتراضي
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
 
63
+ def initialize_openai_client(self):
64
+ """تهيئة اتصال OpenAI"""
 
 
 
 
 
65
  try:
66
+ # التحقق من وجود مفتاح API
67
+ api_key = os.environ.get("OPENAI_API_KEY")
68
+ if not api_key:
69
+ st.session_state.api_key_error = True
70
+ return None
71
+
72
+ # إنشاء عميل OpenAI
73
+ if openai_available:
74
+ return OpenAI()
75
+ return None
 
 
 
 
76
  except Exception as e:
77
+ logging.error(f"خطأ في تهيئة اتصال OpenAI: {str(e)}")
78
+ st.session_state.api_key_error = True
79
+ return None
 
80
 
81
+ def load_conversation_history(self):
82
+ """تحميل سجل المحادثات من الملف"""
83
  try:
84
+ history_path = Path("data/assistant_history.json")
85
+ if history_path.exists():
86
+ with open(history_path, "r", encoding="utf-8") as f:
87
+ history = json.load(f)
88
+ # تحميل آخر 10 رسائل فقط
89
+ if 'history' in history and len(history['history']) > 0:
90
+ st.session_state.ai_messages = history['history'][-10:]
 
 
 
 
91
  except Exception as e:
92
+ logging.error(f"خطأ في تحميل سجل المحادثات: {str(e)}")
 
93
 
94
+ def save_conversation_history(self):
95
+ """حفظ سجل المحادثات إلى ملف"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
  try:
97
+ history_path = Path("data/assistant_history.json")
98
+ history_path.parent.mkdir(exist_ok=True, parents=True)
 
 
 
 
99
 
100
+ # تحديث أو إنشاء ملف جديد
101
+ if history_path.exists():
102
+ with open(history_path, "r", encoding="utf-8") as f:
103
+ history = json.load(f)
104
+ if 'history' in history:
105
+ # إضافة المحادثة الحالية وحفظ آخر 50 محادثة فقط
106
+ history['history'] = history['history'] + st.session_state.ai_messages
107
+ history['history'] = history['history'][-50:]
108
+ else:
109
+ history['history'] = st.session_state.ai_messages
110
+ else:
111
+ history = {'history': st.session_state.ai_messages}
112
+
113
+ with open(history_path, "w", encoding="utf-8") as f:
114
+ json.dump(history, f, ensure_ascii=False, indent=2)
 
 
 
 
 
 
 
 
 
115
  except Exception as e:
116
+ logging.error(f"خطأ في حفظ سجل المحادثات: {str(e)}")
 
 
 
 
 
117
 
118
+ def render(self):
119
+ """عرض واجهة المساعد الذكي"""
120
+ st.markdown("<h1 class='app-title'>المساعد الذكي</h1>", unsafe_allow_html=True)
 
 
 
 
121
 
 
122
  st.markdown("""
123
+ <div class="section-card">
124
+ <p>المساعد الذكي هو واجهة تفاعلية مدعومة بتقنيات الذكاء الاصطناعي لمساعدتك في جميع أنشطة إدارة المشاريع والعقود.
125
+ يمكنك طرح أسئلة بلغتك الطبيعية والحصول على إجابات فورية، أو طلب مساعدة في مهام محددة مثل تحليل بنود العقد أو تقدير التكاليف.</p>
126
+ </div>
127
+ """, unsafe_allow_html=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
128
 
129
+ # اختيار سياق المحادثة
130
+ self._render_context_selector()
 
131
 
132
+ # عرض محتويات المحادثة
133
+ self._render_chat_messages()
 
 
 
 
134
 
135
+ # نموذج إدخال الرسالة
136
+ self._render_chat_input()
 
 
 
137
 
138
+ # إذا كان هناك مشكلة في مفتاح API
139
+ if st.session_state.api_key_error:
140
+ st.error("""
141
+ لم يتم العثور على مفتاح API صالح لخدمة OpenAI.
142
+
143
+ يرجى التواصل مع مسؤول النظام لتكوين المفتاح بشكل صحيح.
144
+ """)
 
 
 
 
 
 
 
 
145
 
146
+ # تنبيه: الوحدة قيد التطوير
147
+ st.info("""
148
+ المساعد الذكي في الوضع التجريبي. بعض الميزات ��د لا تعمل كما هو متوقع.
 
 
149
 
150
+ سيتم إضافة المزيد من القدرات والتكامل مع النماذج المتقدمة مثل Claude-3.7 في الإصدارات القادمة.
151
+ """)
152
+
153
+ def _render_context_selector(self):
154
+ """عرض محدد سياق المحادثة"""
155
+ st.markdown("### سياق المحادثة")
156
 
157
+ col1, col2, col3 = st.columns(3)
158
 
159
  with col1:
160
+ if st.button("عام", key="general_context",
161
+ use_container_width=True,
162
+ type="primary" if st.session_state.assistant_context == "عام" else "secondary"):
163
+ st.session_state.assistant_context = "عام"
164
  st.rerun()
165
+
166
  with col2:
167
+ if st.button("تحليل العقود", key="contract_context",
168
+ use_container_width=True,
169
+ type="primary" if st.session_state.assistant_context == "تحليل العقود" else "secondary"):
170
+ st.session_state.assistant_context = "تحليل العقود"
171
  st.rerun()
172
+
173
  with col3:
174
+ if st.button("حساب التكاليف", key="cost_context",
175
+ use_container_width=True,
176
+ type="primary" if st.session_state.assistant_context == "حساب التكاليف" else "secondary"):
177
+ st.session_state.assistant_context = "حساب التكاليف"
178
  st.rerun()
179
 
180
+ st.markdown("<hr>", unsafe_allow_html=True)
181
+
182
+ def _render_chat_messages(self):
183
+ """عرض رسائل المحادثة"""
184
+ st.markdown("### المحادثة")
185
 
186
+ # عرض رسائل المحادثة
187
+ for message in st.session_state.ai_messages:
188
+ if message["role"] == "user":
189
+ st.markdown(f"""
190
+ <div style="background-color: #E3F2FD; border-radius: 10px; padding: 10px; margin: 5px 0 5px auto; max-width: 80%; text-align: right; direction: rtl;">
191
+ <p style="margin: 0;">{message["content"]}</p>
192
+ <small style="color: #666;">{message.get("time", "")}</small>
193
+ </div>
194
+ """, unsafe_allow_html=True)
195
+ else:
196
+ st.markdown(f"""
197
+ <div style="background-color: #F5F5F5; border-radius: 10px; padding: 10px; margin: 5px auto 5px 0; max-width: 80%; text-align: right; direction: rtl;">
198
+ <p style="margin: 0;">{message["content"]}</p>
199
+ <small style="color: #666;">{message.get("time", "")}</small>
200
+ </div>
201
+ """, unsafe_allow_html=True)
202
+
203
+ # إذا كان في انتظار الإجابة
204
+ if st.session_state.waiting_for_answer:
205
+ with st.spinner("جاري التفكير..."):
206
+ st.markdown("""
207
+ <div style="background-color: #F5F5F5; border-radius: 10px; padding: 10px; margin: 5px auto 5px 0; max-width: 80%; text-align: right;">
208
+ <div class="typing-indicator">
209
+ <span></span>
210
+ <span></span>
211
+ <span></span>
212
+ </div>
213
+ </div>
214
+ """, unsafe_allow_html=True)
215
+
216
+ def _render_chat_input(self):
217
+ """عرض حقل إدخال المحادثة"""
218
+ # مربع الإدخال
219
+ user_input = st.text_area("اكتب سؤالك هنا", key="user_question", height=100)
220
 
221
+ col1, col2 = st.columns([4, 1])
222
 
223
+ with col1:
224
+ # تحديد أزرار السياق السريع
225
+ st.markdown("#### اختصارات سريعة:")
226
+ quick_buttons = st.columns(4)
 
 
 
 
 
227
 
228
+ quick_prompts = [
229
+ "كيف يمكنني تحليل مناقصة؟",
230
+ "كيف أقوم بتقدير تكاليف مشروع؟",
231
+ "ما هي المخاطر التعاقدية؟",
232
+ "كيف أستخدم النظام؟"
233
+ ]
234
 
235
+ for i, prompt in enumerate(quick_prompts):
236
+ with quick_buttons[i]:
237
+ if st.button(prompt, key=f"quick_{i}", use_container_width=True):
238
+ # إرسال السؤال السريع
239
+ self.process_user_message(prompt)
240
+ st.rerun()
241
 
242
+ with col2:
243
+ st.markdown("<br>", unsafe_allow_html=True)
244
+ # زر الإرسال
245
+ if st.button("إرسال", key="send_button", use_container_width=True, type="primary"):
246
+ if user_input.strip():
247
+ self.process_user_message(user_input)
248
+ st.rerun()
249
+
250
+ def process_user_message(self, message):
251
+ """معالجة رسالة المستخدم"""
252
+ if not message.strip():
253
+ return
 
 
 
 
 
 
 
 
 
254
 
255
+ # إضافة رسالة المستخدم إلى المحادثة
256
+ current_time = datetime.now().strftime("%H:%M")
257
+ st.session_state.ai_messages.append({
258
+ "role": "user",
259
+ "content": message,
260
+ "time": current_time
261
+ })
 
 
 
 
262
 
263
+ # تعيين حالة الانتظار
264
+ st.session_state.waiting_for_answer = True
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
265
 
266
+ # الحصول على سياق المحادثة الحالي
267
+ context = st.session_state.assistant_context
268
 
269
+ # الحصول على رد من API (معالجة غير متزامنة)
270
+ try:
271
+ # فحص توفر OpenAI
272
+ if not openai_available or not self.openai_client:
273
+ response = self.get_fallback_response(context, message)
274
+ else:
275
+ response = self.get_ai_response(context, message)
 
 
 
 
276
 
277
+ # إضافة رد المساعد إلى المحادثة
278
+ st.session_state.ai_messages.append({
279
+ "role": "assistant",
280
+ "content": response,
281
+ "time": datetime.now().strftime("%H:%M")
282
+ })
283
+
284
+ # حفظ المحادثة
285
+ self.save_conversation_history()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
286
 
287
+ except Exception as e:
288
+ logging.error(f"خطأ في معالجة رسالة المستخدم: {str(e)}")
289
+ st.session_state.ai_messages.append({
290
+ "role": "assistant",
291
+ "content": "عذراً، حدث خطأ أثناء معالجة طلبك. يرجى المحاولة مرة أخرى لاحقاً.",
292
+ "time": datetime.now().strftime("%H:%M")
293
+ })
294
+
295
+ # إلغاء حالة الانتظار
296
+ st.session_state.waiting_for_answer = False
297
+
298
+ def get_ai_response(self, context, message):
299
+ """الحصول على رد من OpenAI API"""
300
+ try:
301
+ # إنشاء رسالة النظام بناءً على السياق
302
+ system_message = self.get_system_message(context)
303
 
304
+ # تحضير سجل المحادثة للإرسال إلى OpenAI
305
+ messages = [{"role": "system", "content": system_message}]
 
 
 
306
 
307
+ # إضافة آخر 5 رسائل من المحادثة الحالية
308
+ history = [msg for msg in st.session_state.ai_messages[-10:] if msg["role"] in ["user", "assistant"]]
309
+ for msg in history:
310
+ messages.append({"role": msg["role"], "content": msg["content"]})
 
311
 
312
+ # إضافة رسالة المستخدم الحالية إذا لم تكن موجودة بالفعل
313
+ if history and history[-1]["role"] != "user":
314
+ messages.append({"role": "user", "content": message})
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
315
 
316
+ # استدعاء OpenAI API
317
+ response = self.openai_client.chat.completions.create(
318
+ model="gpt-4o",
319
+ messages=messages,
320
+ temperature=0.7,
321
+ max_tokens=1000
322
+ )
323
 
324
+ return response.choices[0].message.content
325
+
326
+ except Exception as e:
327
+ logging.error(f"خطأ في الحصول على رد من OpenAI: {str(e)}")
328
+ return self.get_fallback_response(context, message)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
329
 
330
+ def get_system_message(self, context):
331
+ """إنشاء رسالة النظام بناءً على سياق المحادثة"""
332
+ if context == "تحليل العقود":
333
+ return """
334
+ أنت مساعد متخصص في تحليل العقود والمناقصات في مجال المقاولات والإنشاءات.
335
+ ساعد المستخدم في فهم البنود القانونية وتحديد المخاطر المحتملة وتقديم النصائح حول تحسين الشروط.
336
+ استخدم لغة واضحة ومهنية باللغة العربية واذكر المصطلحات الفنية والقانونية المناسبة.
337
+ """
338
+ elif context == "حساب التكاليف":
339
+ return """
340
+ أنت مساعد متخصص في تقدير تكاليف مشاريع البناء والمقاولات.
341
+ ساعد المستخدم في فهم كيفية حساب تكاليف المواد والعمالة والمعدات، وكيفية تسعير بنود المشروع بشكل صحيح.
342
+ قدم معلومات حول طرق التسعير المختلفة مثل وحدة القياس والمبلغ المقطوع.
343
+ استخدم لغة واضحة ومهنية باللغة العربية واذكر المصطلحات الفنية المناسبة.
344
+ """
345
+ else: # سياق عام
346
+ return """
347
+ أنت مساعد ذكي متخصص في مجال المقاولات والإنشاءات باسم "واهبي" من نظام تحليل العقود والمناقصات.
348
+ ساعد المستخدم بالإجابة على أسئلته حول إدارة المشاريع وتحليل العقود وتقدير التكاليف والمناقصات.
349
+ تجنب التعليق على مواضيع لا علاقة لها بالمقاولات والإنشاءات.
350
+ استخدم لغة واضحة ومهنية باللغة العربية.
351
+ """
352
+
353
+ def get_fallback_response(self, context, message):
354
+ """الحصول على رد احتياطي في حالة عدم إمكانية الوصول إلى API"""
355
+ responses = {
356
+ "تحليل العقود": """
357
+ مرحباً! أنا مساعدك في تحليل العقود والمناقصات. للأسف، هناك مشكلة في الاتصال بخدمة الذكاء الاصطناعي حالياً.
358
+
359
+ للمساعدة في تحليل العقود، يمكنك استخدام وحدة تحليل المستندات في النظام، والتي تتيح لك:
360
+
361
+ - تحميل ملفات العقود بصيغة PDF
362
+ - تحليل البنود والشروط تلقائياً
363
+ - استخراج الالتزامات والمواعيد النهائية
364
+ - تحليل المخاطر المحتملة
365
+
366
+ يمكنك الوصول إلى هذه الوحدة من القائمة الجانبية تحت "تحليل المستندات".
367
+ """,
368
+
369
+ "حساب التكاليف": """
370
+ مرحباً! أنا مساعدك في تقدير تكاليف المشاريع. للأسف، هناك مشكلة في الاتصال بخدمة الذكاء الاصطناعي حالياً.
371
+
372
+ للمساعدة في حساب التكاليف، يمكنك استخدام وحدة التسعير المتكاملة في النظام، والتي تتيح لك:
373
+
374
+ - إنشاء نماذج تسعير متكاملة
375
+ - حساب تكاليف المواد والعمالة والمعدات
376
+ - تطبيق نسب الأرباح والمصاريف الإدارية
377
+ - إنشاء جداول كميات تفصيلية
378
+
379
+ يمكنك الوصول إلى هذه الوحدة من القائمة الجانبية تحت "التسعير المتكاملة".
380
+ """,
381
+
382
+ "عام": """
383
+ مرحباً! أنا مساعدك في نظام تحليل العقود والمناقصات. للأسف، هناك مشكلة في الاتصال بخدمة الذكاء الاصطناعي حالياً.
384
+
385
+ يمكنك الاستفادة من الوظائف المتاحة في النظام مثل:
386
+
387
+ - تحليل المستن��ات لفهم العقود والمناقصات
388
+ - التسعير المتكاملة لحساب تكاليف المشاريع
389
+ - إدارة المشاريع لمتابعة سير العمل
390
+ - تقييم مخاطر العقود لتقليل المخاطر المحتملة
391
+
392
+ يمكنك الوصول إلى هذه الوحدات من القائمة الجانبية.
393
+ """
394
+ }
395
 
396
+ return responses.get(context, responses["عام"])
 
397
 
398
 
399
+ # مثال للاستخدام المستقل للوحدة
400
  if __name__ == "__main__":
401
  st.set_page_config(
402
  page_title="المساعد الذكي | WAHBi AI",
 
405
  initial_sidebar_state="expanded"
406
  )
407
 
408
+ # استيراد مكونات واجهة المستخدم
409
+ from utils.components.sidebar import render_sidebar
410
+
411
+ # عرض الشريط الجانبي
412
+ render_sidebar()
413
+
414
+ # عرض واجهة المساعد الذكي
415
  assistant = AIAssistant()
416
  assistant.render()
modules/ai_assistant/assistant_app.py CHANGED
@@ -2,8 +2,8 @@
2
  # -*- coding: utf-8 -*-
3
 
4
  """
5
- تطبيق المساعد الذكي التفاعلي
6
- يتيح للمستخدمين التفاعل مع نماذج الذكاء الاصطناعي المتقدمة للحصول على مساعدة في تحليل العقود والمناقصات
7
  """
8
 
9
  import os
@@ -16,11 +16,32 @@ import numpy as np
16
  sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "../..")))
17
 
18
  # استيراد مكونات المساعد الذكي
19
- from modules.ai_assistant.ai_assistant import AIAssistant
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
 
21
 
22
  class AssistantApp:
23
- """تطبيق المساعد الذكي التفاعلي"""
24
 
25
  def __init__(self):
26
  """تهيئة تطبيق المساعد الذكي"""
@@ -40,5 +61,12 @@ if __name__ == "__main__":
40
  initial_sidebar_state="expanded"
41
  )
42
 
43
- app = AssistantApp()
44
- app.render()
 
 
 
 
 
 
 
 
2
  # -*- coding: utf-8 -*-
3
 
4
  """
5
+ تطبيق المساعد الذكي لنظام واهبي لتحليل العقود والمناقصات
6
+ AI Assistant App for WAHBI Tender Analysis System
7
  """
8
 
9
  import os
 
16
  sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "../..")))
17
 
18
  # استيراد مكونات المساعد الذكي
19
+ try:
20
+ from modules.ai_assistant.ai_assistant import AIAssistant
21
+ except ImportError:
22
+ # في حالة عدم وجود الملف، نستخدم تعريف مؤقت
23
+ class AIAssistant:
24
+ """فئة مؤقتة للمساعد الذكي"""
25
+ def render(self):
26
+ """عرض واجهة المساعد الذكي المؤقتة"""
27
+ st.markdown("<h1 class='app-title'>المساعد الذكي</h1>", unsafe_allow_html=True)
28
+
29
+ st.info("""
30
+ مكون المساعد الذكي قيد التطوير حاليًا. سيتم إضافة هذه الميزة في الإصدار القادم.
31
+ """)
32
+
33
+ st.markdown("""
34
+ ### الوظائف القادمة:
35
+ - محادثة ذكية معتمدة على تقنيات GPT-4o وClaude-3.7 المتقدمة
36
+ - فهم الطلبات باللغة العربية بشكل كامل
37
+ - القدرة على إنشاء مستندات واستمارات بناءً على الطلب
38
+ - مساعدة في تحليل العقود وشروط المناقصات
39
+ - إمكانية استخراج معلومات من وثائق مختلفة
40
+ """)
41
 
42
 
43
  class AssistantApp:
44
+ """تطبيق المساعد الذكي"""
45
 
46
  def __init__(self):
47
  """تهيئة تطبيق المساعد الذكي"""
 
61
  initial_sidebar_state="expanded"
62
  )
63
 
64
+ # استيراد مكونات واجهة المستخدم
65
+ from utils.components.sidebar import render_sidebar
66
+
67
+ # عرض الشريط الجانبي
68
+ render_sidebar()
69
+
70
+ # عرض واجهة المساعد الذكي
71
+ assistant_app = AssistantApp()
72
+ assistant_app.render()
utils/components/sidebar.py CHANGED
@@ -8,6 +8,38 @@ import os
8
  from pathlib import Path
9
  import streamlit_option_menu as option_menu
10
  import json
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
 
12
  def get_user_info():
13
  """
@@ -17,65 +49,306 @@ def get_user_info():
17
  return {
18
  "name": "محمد أحمد",
19
  "role": "محلل عقود",
 
 
20
  "image": None
21
  }
22
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  def render_sidebar():
24
  """
25
  عرض الشريط الجانبي الرئيسي للتطبيق
26
  """
27
  with st.sidebar:
 
 
 
28
  # عرض معلومات المستخدم
29
  user = get_user_info()
30
 
31
- # مربع معلومات المستخدم
32
  st.markdown(f"""
33
- <div style="padding: 1rem; background: linear-gradient(135deg, #f0f7ff, #e8f1fb); border-radius: 10px; margin-bottom: 1.5rem; text-align: center;">
34
- <div style="width: 80px; height: 80px; background: linear-gradient(135deg, #1E88E5, #64B5F6); border-radius: 50%; margin: 0 auto 0.8rem auto; display: flex; justify-content: center; align-items: center; color: white; font-size: 2rem; font-weight: bold;">
35
  {user["name"][0] if user["name"] else "م"}
36
  </div>
37
- <h3 style="margin: 0; font-size: 1.2rem; color: #333;">{user["name"]}</h3>
38
- <p style="margin: 0; color: #1E88E5; font-size: 0.9rem;">{user["role"]}</p>
 
 
 
 
 
 
39
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
  """, unsafe_allow_html=True)
41
 
42
  # القائمة الرئيسية باستخدام كومبوننت الشريط الجانبي
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
  selected = option_menu.option_menu(
44
- menu_title="الوصول السريع",
45
- options=[
46
- "الرئيسية",
47
- "تحليل العقود",
48
- "حاسبة التكاليف",
49
- "إدارة المشاريع",
50
- "الخريطة التفاعلية",
51
- "المساعد الذكي",
52
- "التقارير",
53
- "الإعدادات"
54
- ],
55
- icons=[
56
- "house-fill",
57
- "file-earmark-text-fill",
58
- "calculator-fill",
59
- "clipboard2-data-fill",
60
- "geo-alt-fill",
61
- "robot",
62
- "bar-chart-fill",
63
- "gear-fill"
64
- ],
65
- menu_icon="list",
66
  default_index=0,
67
  styles={
68
- "container": {"padding": "0!important", "background-color": "transparent", "direction": "rtl"},
69
- "icon": {"color": "#1E88E5", "font-size": "1rem", "float": "right", "margin-left": "10px"},
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70
  "nav-link": {
71
- "font-size": "0.9rem",
72
  "text-align": "right",
73
  "direction": "rtl",
74
- "--hover-color": "#E3F2FD",
75
- "margin-bottom": "0.2rem",
76
- "padding-right": "15px",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
77
  },
78
- "nav-link-selected": {"background-color": "#1E88E5", "color": "white", "text-align": "right"},
79
  }
80
  )
81
 
@@ -83,32 +356,142 @@ def render_sidebar():
83
  st.session_state["sidebar_selected"] = selected
84
 
85
  # إظهار حالة الاتصال بقاعدة البيانات وحالة النظام
86
- st.markdown("""
87
- <div style="padding: 1rem; background-color: #f0f2f5; border-radius: 10px; margin-top: 1.5rem;">
88
- <h4 style="margin: 0 0 0.8rem 0; font-size: 1rem; color: #333;">حالة النظام</h4>
89
- <div style="display: flex; align-items: center; margin-bottom: 0.5rem;">
90
- <div style="width: 8px; height: 8px; border-radius: 50%; background-color: #4CAF50; margin-left: 0.5rem;"></div>
91
- <span style="font-size: 0.9rem; color: #666;">قاعدة البيانات متصلة</span>
 
92
  </div>
93
- <div style="display: flex; align-items: center; margin-bottom: 0.5rem;">
94
- <div style="width: 8px; height: 8px; border-radius: 50%; background-color: #4CAF50; margin-left: 0.5rem;"></div>
95
- <span style="font-size: 0.9rem; color: #666;">واجهة برمجة التطبيقات</span>
 
96
  </div>
97
- <div style="display: flex; align-items: center;">
98
- <div style="width: 8px; height: 8px; border-radius: 50%; background-color: #4CAF50; margin-left: 0.5rem;"></div>
99
- <span style="font-size: 0.9rem; color: #666;">الذكاء الاصطناعي</span>
 
 
 
 
 
100
  </div>
101
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
102
  """, unsafe_allow_html=True)
103
 
104
  # معلومات النظام وعنوان المشروع
105
  with st.expander("حول النظام", expanded=False):
106
- st.markdown("""
107
- <div style="font-size: 0.9rem; color: #666;">
108
- <p style="margin-bottom: 0.5rem;">نظام واهبي للذكاء الاصطناعي - إصدار 2.0</p>
109
- <p style="margin-bottom: 0.5rem;">تحليل العقود والمناقصات</p>
110
- <p style="margin: 0;" 2025 جميع الحقوق محفوظة</p>
 
 
 
 
 
 
 
 
 
 
 
 
 
111
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
  """, unsafe_allow_html=True)
113
 
114
  def get_sidebar_selection():
@@ -128,43 +511,224 @@ def render_module_sidebar(module_name, options=[]):
128
  with st.sidebar:
129
  # عنوان الوحدة
130
  st.markdown(f"""
131
- <h3 style="margin-bottom: 1rem; color: #1E88E5; font-size: 1.2rem; padding-bottom: 0.5rem; border-bottom: 1px solid #eee;">
132
  {module_name}
133
- </h3>
 
 
 
 
 
 
 
 
 
 
 
134
  """, unsafe_allow_html=True)
135
 
136
  # إذا تم توفير خيارات للوحدة
137
  if options:
138
- selected = option_menu.option_menu(
139
- menu_title=None,
140
- options=options,
141
- menu_icon=None,
142
- default_index=0,
143
- styles={
144
- "container": {"padding": "0!important", "background-color": "transparent", "direction": "rtl"},
145
- "icon": {"color": "#1E88E5", "font-size": "1rem", "float": "right", "margin-left": "10px"},
146
- "nav-link": {
147
- "font-size": "0.9rem",
148
- "text-align": "right",
149
- "direction": "rtl",
150
- "--hover-color": "#E3F2FD",
151
- "margin-bottom": "0.2rem",
152
- "padding-right": "15px",
153
- "padding": "0.5rem"
154
- },
155
- "nav-link-selected": {"background-color": "#1E88E5", "color": "white", "text-align": "right"},
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
156
  }
157
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
158
 
159
  # تخزين الخيار المحدد
160
  st.session_state[f"{module_name}_selected"] = selected
161
 
162
  return selected
163
 
164
- # زر للعودة إلى القائمة الرئيسية
165
- if st.button("العودة للقائمة الرئيسية", key=f"back_btn_{module_name}"):
166
- st.session_state["sidebar_selected"] = "الرئيسية"
167
- st.rerun()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
168
 
169
  def get_module_selection(module_name):
170
  """
 
8
  from pathlib import Path
9
  import streamlit_option_menu as option_menu
10
  import json
11
+ import datetime
12
+
13
+ # ألوان النظام الموحدة
14
+ COLORS = {
15
+ "primary": "#0B6E4F",
16
+ "secondary": "#08603a",
17
+ "accent": "#FFB100",
18
+ "tertiary": "#5754FF",
19
+ "quaternary": "#f43f5e",
20
+ "success": "#10b981",
21
+ "warning": "#f59e0b",
22
+ "danger": "#ef4444",
23
+ "light_bg": "#f8fafc",
24
+ "text": "#334155",
25
+ "heading": "#1e293b",
26
+ "muted": "#64748b",
27
+ "border": "#e2e8f0",
28
+ }
29
+
30
+ # تهيئة الرموز مع ألوان مخصصة للأقسام المختلفة
31
+ SECTION_ICONS = {
32
+ "الرئيسية": {"icon": "house-fill", "color": COLORS["primary"]},
33
+ "تحليل العقود": {"icon": "file-earmark-text-fill", "color": COLORS["primary"]},
34
+ "حاسبة التكاليف": {"icon": "calculator-fill", "color": COLORS["tertiary"]},
35
+ "إدارة المشاريع": {"icon": "clipboard2-data-fill", "color": COLORS["primary"]},
36
+ "الخريطة التفاعلية": {"icon": "geo-alt-fill", "color": COLORS["quaternary"]},
37
+ "المساعد الذكي": {"icon": "robot", "color": COLORS["accent"]},
38
+ "التقارير": {"icon": "bar-chart-fill", "color": COLORS["tertiary"]},
39
+ "المحتوى المحلي": {"icon": "flag-fill", "color": COLORS["success"]},
40
+ "تحليل المخاطر": {"icon": "shield-fill-exclamation", "color": COLORS["warning"]},
41
+ "الإعدادات": {"icon": "gear-fill", "color": COLORS["muted"]},
42
+ }
43
 
44
  def get_user_info():
45
  """
 
49
  return {
50
  "name": "محمد أحمد",
51
  "role": "محلل عقود",
52
+ "organization": "شركة المشاريع المتطورة",
53
+ "last_login": datetime.datetime.now().strftime("%Y-%m-%d %H:%M"),
54
  "image": None
55
  }
56
 
57
+ def render_wahbi_logo():
58
+ """
59
+ عرض شعار نظام واهبي بتصميم SVG متقدم
60
+ """
61
+ logo_html = """
62
+ <div style="text-align: center; margin-bottom: 1.5rem; margin-top: 0.5rem;">
63
+ <svg width="120" height="60" viewBox="0 0 240 120" xmlns="http://www.w3.org/2000/svg">
64
+ <style>
65
+ .logo-text { font-family: 'Almarai', sans-serif; font-weight: 800; }
66
+ .logo-accent { fill: #FFB100; }
67
+ .logo-primary { fill: #0B6E4F; }
68
+ .logo-secondary { fill: #08603a; }
69
+ @keyframes pulse {
70
+ 0% { opacity: 0.8; }
71
+ 50% { opacity: 1; }
72
+ 100% { opacity: 0.8; }
73
+ }
74
+ .pulse { animation: pulse 2s infinite ease-in-out; }
75
+ </style>
76
+ <g>
77
+ <!-- الشكل الخارجي -->
78
+ <path class="logo-primary" d="M40,20 L200,20 C220,20 230,30 230,50 L230,70 C230,90 220,100 200,100 L40,100 C20,100 10,90 10,70 L10,50 C10,30 20,20 40,20 Z" />
79
+
80
+ <!-- الشكل الداخلي -->
81
+ <path class="logo-secondary" d="M45,30 L195,30 C210,30 220,40 220,55 L220,65 C220,80 210,90 195,90 L45,90 C30,90 20,80 20,65 L20,55 C20,40 30,30 45,30 Z" />
82
+
83
+ <!-- الشكل الثالث (الهالة) -->
84
+ <circle class="pulse logo-accent" cx="120" cy="60" r="35" opacity="0.2" />
85
+
86
+ <!-- نص "واهبي" -->
87
+ <text class="logo-text" x="120" y="70" font-size="40" text-anchor="middle" fill="white">واهبي</text>
88
+
89
+ <!-- نص "AI" -->
90
+ <text class="logo-text logo-accent" x="175" y="70" font-size="30" text-anchor="middle">AI</text>
91
+ </g>
92
+ </svg>
93
+ </div>
94
+ """
95
+ return logo_html
96
+
97
  def render_sidebar():
98
  """
99
  عرض الشريط الجانبي الرئيسي للتطبيق
100
  """
101
  with st.sidebar:
102
+ # عرض شعار النظام
103
+ st.markdown(render_wahbi_logo(), unsafe_allow_html=True)
104
+
105
  # عرض معلومات المستخدم
106
  user = get_user_info()
107
 
108
+ # مربع معلومات المستخدم بتصميم متقدم
109
  st.markdown(f"""
110
+ <div class="user-profile-card">
111
+ <div class="user-avatar">
112
  {user["name"][0] if user["name"] else "م"}
113
  </div>
114
+ <h3 class="user-name">{user["name"]}</h3>
115
+ <p class="user-role">{user["role"]}</p>
116
+ <p class="user-organization">{user["organization"]}</p>
117
+
118
+ <div class="user-last-login">
119
+ <i class="fas fa-clock"></i>
120
+ آخر دخول: {user["last_login"]}
121
+ </div>
122
  </div>
123
+
124
+ <style>
125
+ .user-profile-card {{
126
+ padding: var(--spacing-lg);
127
+ background: linear-gradient(135deg, rgba(11, 110, 79, 0.08), rgba(11, 110, 79, 0.03));
128
+ border-radius: var(--border-radius);
129
+ margin-bottom: var(--spacing-lg);
130
+ text-align: center;
131
+ border: 1px solid rgba(11, 110, 79, 0.12);
132
+ box-shadow: var(--shadow-sm);
133
+ }}
134
+
135
+ .user-avatar {{
136
+ width: 85px;
137
+ height: 85px;
138
+ background: var(--primary-gradient);
139
+ border-radius: var(--border-radius-circle);
140
+ margin: 0 auto var(--spacing-md) auto;
141
+ display: flex;
142
+ justify-content: center;
143
+ align-items: center;
144
+ color: white;
145
+ font-size: 2.2rem;
146
+ font-weight: var(--font-weight-bold);
147
+ box-shadow: 0 4px 10px rgba(11, 110, 79, 0.3);
148
+ }}
149
+
150
+ .user-name {{
151
+ margin: 0;
152
+ font-size: var(--font-size-xl);
153
+ color: var(--gray-800);
154
+ font-weight: var(--font-weight-bold);
155
+ }}
156
+
157
+ .user-role {{
158
+ margin: var(--spacing-xs) 0 var(--spacing-xs) 0;
159
+ color: var(--primary-color);
160
+ font-size: var(--font-size-sm);
161
+ font-weight: var(--font-weight-semibold);
162
+ }}
163
+
164
+ .user-organization {{
165
+ margin: 0;
166
+ color: var(--gray-600);
167
+ font-size: var(--font-size-xs);
168
+ }}
169
+
170
+ .user-last-login {{
171
+ margin-top: var(--spacing-md);
172
+ padding-top: var(--spacing-md);
173
+ border-top: 1px dashed rgba(11, 110, 79, 0.15);
174
+ text-align: center;
175
+ font-size: var(--font-size-xs);
176
+ color: var(--gray-500);
177
+ display: flex;
178
+ align-items: center;
179
+ justify-content: center;
180
+ }}
181
+
182
+ .user-last-login i {{
183
+ margin-left: 5px;
184
+ }}
185
+ </style>
186
  """, unsafe_allow_html=True)
187
 
188
  # القائمة الرئيسية باستخدام كومبوننت الشريط الجانبي
189
+ menu_options = [
190
+ "الرئيسية",
191
+ "تحليل العقود",
192
+ "حاسبة التكاليف",
193
+ "إدارة المشاريع",
194
+ "الخريطة التفاعلية",
195
+ "المساعد الذكي",
196
+ "التقارير",
197
+ "المحتوى المحلي",
198
+ "تحليل المخاطر",
199
+ "الإعدادات"
200
+ ]
201
+
202
+ icons = [SECTION_ICONS[option]["icon"] for option in menu_options]
203
+
204
+ # توليد قائمة الألوان المخصصة للأيقونات
205
+ icon_colors = [SECTION_ICONS[option]["color"] for option in menu_options]
206
+
207
+ # تطبيق نمط CSS المخصص للقائمة
208
+ menu_style = """
209
+ <style>
210
+ /* تحسين تنسيق القائمة الرئيسية */
211
+ .nav-link {
212
+ position: relative !important;
213
+ overflow: hidden !important;
214
+ white-space: nowrap !important;
215
+ }
216
+
217
+ /* تأثير التوهج للعنصر المحدد */
218
+ .nav-link.active::before {
219
+ content: '';
220
+ position: absolute;
221
+ top: 0;
222
+ right: 0;
223
+ width: 4px;
224
+ height: 100%;
225
+ background: linear-gradient(to bottom, rgba(255, 177, 0, 0.8), rgba(255, 177, 0, 0.3));
226
+ z-index: 5;
227
+ animation: pulse-border 1.5s infinite alternate;
228
+ }
229
+
230
+ /* تأثير الخلفية للعنصر المحدد */
231
+ .nav-link.active::after {
232
+ content: '';
233
+ position: absolute;
234
+ top: 0;
235
+ right: 0;
236
+ width: 100%;
237
+ height: 100%;
238
+ background: linear-gradient(135deg, rgba(11, 110, 79, 0.95), rgba(8, 96, 58, 0.95));
239
+ z-index: -1;
240
+ animation: gradient-shift 8s infinite alternate;
241
+ }
242
+
243
+ /* تنسيق الأيقونات بالألوان المخصصة */
244
+ .section-icon-0 { color: #0B6E4F !important; }
245
+ .section-icon-1 { color: #0B6E4F !important; }
246
+ .section-icon-2 { color: #5754FF !important; }
247
+ .section-icon-3 { color: #0B6E4F !important; }
248
+ .section-icon-4 { color: #f43f5e !important; }
249
+ .section-icon-5 { color: #FFB100 !important; }
250
+ .section-icon-6 { color: #5754FF !important; }
251
+ .section-icon-7 { color: #10b981 !important; }
252
+ .section-icon-8 { color: #f59e0b !important; }
253
+ .section-icon-9 { color: #64748b !important; }
254
+
255
+ /* إظهار الأيقونات بالأبيض للعنصر المحدد */
256
+ .nav-link.active i {
257
+ color: white !important;
258
+ animation: icon-pop 0.3s ease-out;
259
+ }
260
+
261
+ /* تأثيرات الحركة */
262
+ @keyframes pulse-border {
263
+ 0% { opacity: 0.7; }
264
+ 100% { opacity: 1; }
265
+ }
266
+
267
+ @keyframes gradient-shift {
268
+ 0% { background-position: 0% 50%; }
269
+ 50% { background-position: 100% 50%; }
270
+ 100% { background-position: 0% 50%; }
271
+ }
272
+
273
+ @keyframes icon-pop {
274
+ 0% { transform: scale(1); }
275
+ 50% { transform: scale(1.2); }
276
+ 100% { transform: scale(1); }
277
+ }
278
+
279
+ /* تأثير التحويم */
280
+ .nav-link:not(.active):hover {
281
+ background-color: rgba(11, 110, 79, 0.08) !important;
282
+ transform: translateX(-3px) !important;
283
+ }
284
+
285
+ /* تنعيم عملية الانتقال */
286
+ .nav-link {
287
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important;
288
+ }
289
+ </style>
290
+ """
291
+ st.markdown(menu_style, unsafe_allow_html=True)
292
+
293
+ # إضافة عنوان CSS للأيقونات
294
+ for i, option in enumerate(menu_options):
295
+ st.markdown(f"""
296
+ <style>
297
+ div[data-testid="stVerticalBlock"] div.stButton:nth-child({i+1}) button i {{
298
+ color: {SECTION_ICONS[option]["color"]} !important;
299
+ }}
300
+ </style>
301
+ """, unsafe_allow_html=True)
302
+
303
  selected = option_menu.option_menu(
304
+ menu_title="نظام WAHBi AI",
305
+ options=menu_options,
306
+ icons=icons,
307
+ menu_icon="grid-fill",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
308
  default_index=0,
309
  styles={
310
+ "container": {
311
+ "padding": "0.5rem !important",
312
+ "background-color": "transparent",
313
+ "direction": "rtl",
314
+ "border-radius": "var(--border-radius)",
315
+ "margin-bottom": "var(--spacing-md)",
316
+ "border": "1px solid rgba(11, 110, 79, 0.1)",
317
+ "backdrop-filter": "blur(10px)",
318
+ "background": "rgba(255, 255, 255, 0.6)",
319
+ },
320
+ "icon": {
321
+ "font-size": "1.2rem",
322
+ "float": "right",
323
+ "margin-left": "15px",
324
+ "vertical-align": "middle",
325
+ },
326
  "nav-link": {
327
+ "font-size": "0.95rem",
328
  "text-align": "right",
329
  "direction": "rtl",
330
+ "padding": "0.8rem 1rem",
331
+ "margin-bottom": "0.5rem",
332
+ "border-radius": "8px",
333
+ "font-weight": "500",
334
+ "display": "flex",
335
+ "align-items": "center",
336
+ "justify-content": "flex-start",
337
+ "position": "relative",
338
+ "overflow": "hidden",
339
+ "z-index": "1",
340
+ "transition": "all 0.3s ease",
341
+ "background": "rgba(255, 255, 255, 0.7)",
342
+ "border": "1px solid rgba(226, 232, 240, 0.7)",
343
+ },
344
+ "nav-link-selected": {
345
+ "background": "var(--primary-gradient)",
346
+ "color": "white",
347
+ "text-align": "right",
348
+ "font-weight": "600",
349
+ "box-shadow": "0 4px 12px rgba(11, 110, 79, 0.2)",
350
+ "border": "none",
351
  },
 
352
  }
353
  )
354
 
 
356
  st.session_state["sidebar_selected"] = selected
357
 
358
  # إظهار حالة الاتصال بقاعدة البيانات وحالة النظام
359
+ st.markdown(f"""
360
+ <div class="system-status-card">
361
+ <h4 class="status-title">حالة النظام</h4>
362
+
363
+ <div class="status-item">
364
+ <div class="status-indicator active"></div>
365
+ <span class="status-text">قاعدة البيانات متصلة</span>
366
  </div>
367
+
368
+ <div class="status-item">
369
+ <div class="status-indicator active"></div>
370
+ <span class="status-text">واجهة برمجة التطبيقات</span>
371
  </div>
372
+
373
+ <div class="status-item">
374
+ <div class="status-indicator active"></div>
375
+ <span class="status-text">الذكاء الاصطناعي</span>
376
+ </div>
377
+
378
+ <div class="status-footer">
379
+ آخر تحديث: {datetime.datetime.now().strftime("%H:%M:%S")}
380
  </div>
381
  </div>
382
+
383
+ <style>
384
+ .system-status-card {{
385
+ padding: var(--spacing-lg);
386
+ background-color: white;
387
+ border-radius: var(--border-radius);
388
+ margin-top: var(--spacing-lg);
389
+ border: 1px solid var(--gray-200);
390
+ box-shadow: var(--shadow-card);
391
+ }}
392
+
393
+ .status-title {{
394
+ margin: 0 0 var(--spacing-md) 0;
395
+ font-size: var(--font-size-md);
396
+ color: var(--gray-800);
397
+ font-weight: var(--font-weight-semibold);
398
+ border-right: 3px solid var(--primary-color);
399
+ padding-right: var(--spacing-sm);
400
+ }}
401
+
402
+ .status-item {{
403
+ display: flex;
404
+ align-items: center;
405
+ margin-bottom: var(--spacing-sm);
406
+ justify-content: flex-start;
407
+ }}
408
+
409
+ .status-indicator {{
410
+ min-width: 10px;
411
+ height: 10px;
412
+ border-radius: 50%;
413
+ margin-left: var(--spacing-sm);
414
+ }}
415
+
416
+ .status-indicator.active {{
417
+ background-color: var(--success-color);
418
+ box-shadow: 0 0 5px var(--success-color);
419
+ }}
420
+
421
+ .status-indicator.warning {{
422
+ background-color: var(--warning-color);
423
+ box-shadow: 0 0 5px var(--warning-color);
424
+ }}
425
+
426
+ .status-indicator.error {{
427
+ background-color: var(--danger-color);
428
+ box-shadow: 0 0 5px var(--danger-color);
429
+ }}
430
+
431
+ .status-text {{
432
+ font-size: var(--font-size-sm);
433
+ color: var(--gray-700);
434
+ }}
435
+
436
+ .status-footer {{
437
+ margin-top: var(--spacing-md);
438
+ padding-top: var(--spacing-md);
439
+ border-top: 1px solid var(--gray-200);
440
+ font-size: var(--font-size-xs);
441
+ color: var(--gray-500);
442
+ text-align: center;
443
+ }}
444
+ </style>
445
  """, unsafe_allow_html=True)
446
 
447
  # معلومات النظام وعنوان المشروع
448
  with st.expander("حول النظام", expanded=False):
449
+ st.markdown(f"""
450
+ <div class="about-system">
451
+ <div class="about-item">
452
+ <i class="fas fa-info-circle about-icon"></i>
453
+ <span class="about-text about-title">نظام واهبي للذكاء الاصطناعي - إصدار 2.0</span>
454
+ </div>
455
+ <div class="about-item">
456
+ <i class="fas fa-file-contract about-icon"></i>
457
+ <span class="about-text">تحليل العقود والمناقصات</span>
458
+ </div>
459
+ <div class="about-item">
460
+ <i class="fas fa-brain about-icon"></i>
461
+ <span class="about-text">بواسطة نماذج الذكاء الاصطناعي المتقدمة</span>
462
+ </div>
463
+ <div class="about-item">
464
+ <i class="fas fa-copyright about-icon"></i>
465
+ <span class="about-text">© 2025 جميع الحقوق محفوظة</span>
466
+ </div>
467
  </div>
468
+
469
+ <style>
470
+ .about-system {{
471
+ font-size: var(--font-size-sm);
472
+ color: var(--gray-700);
473
+ }}
474
+
475
+ .about-item {{
476
+ display: flex;
477
+ align-items: center;
478
+ margin-bottom: var(--spacing-sm);
479
+ }}
480
+
481
+ .about-icon {{
482
+ color: var(--primary-color);
483
+ font-size: 1rem;
484
+ margin-left: var(--spacing-sm);
485
+ }}
486
+
487
+ .about-text {{
488
+ flex: 1;
489
+ }}
490
+
491
+ .about-title {{
492
+ font-weight: var(--font-weight-semibold);
493
+ }}
494
+ </style>
495
  """, unsafe_allow_html=True)
496
 
497
  def get_sidebar_selection():
 
511
  with st.sidebar:
512
  # عنوان الوحدة
513
  st.markdown(f"""
514
+ <div class="module-title">
515
  {module_name}
516
+ </div>
517
+
518
+ <style>
519
+ .module-title {{
520
+ margin-bottom: var(--spacing-md);
521
+ color: var(--primary-color);
522
+ font-size: var(--font-size-lg);
523
+ font-weight: var(--font-weight-semibold);
524
+ padding-bottom: var(--spacing-sm);
525
+ border-bottom: 1px solid var(--gray-200);
526
+ }}
527
+ </style>
528
  """, unsafe_allow_html=True)
529
 
530
  # إذا تم توفير خيارات للوحدة
531
  if options:
532
+ # تطبيق نمط CSS المخصص للقائمة الفرعية
533
+ module_menu_style = """
534
+ <style>
535
+ /* تحسين تنسيق قائمة الوحدة الفرعية */
536
+ .module-menu .nav-link {
537
+ position: relative !important;
538
+ overflow: hidden !important;
539
+ white-space: nowrap !important;
540
+ background: rgba(250, 250, 250, 0.5) !important;
541
+ border: 1px solid rgba(226, 232, 240, 0.5) !important;
542
+ border-radius: 6px !important;
543
+ margin-bottom: 0.4rem !important;
544
+ padding: 0.6rem 1rem !important;
545
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important;
546
+ }
547
+
548
+ /* تأثير التحويم */
549
+ .module-menu .nav-link:not(.active):hover {
550
+ background-color: rgba(11, 110, 79, 0.05) !important;
551
+ transform: translateX(-2px) !important;
552
+ border-color: rgba(11, 110, 79, 0.15) !important;
553
+ }
554
+
555
+ /* تنسيق العنصر النشط */
556
+ .module-menu .nav-link.active {
557
+ background: linear-gradient(135deg, rgba(11, 110, 79, 0.9), rgba(8, 96, 58, 0.9)) !important;
558
+ color: white !important;
559
+ box-shadow: 0 4px 10px rgba(11, 110, 79, 0.15) !important;
560
+ font-weight: 600 !important;
561
+ border: none !important;
562
+ }
563
+
564
+ /* ترتيب العناصر */
565
+ .module-menu .nav-link::before {
566
+ content: '';
567
+ position: absolute;
568
+ width: 4px;
569
+ height: 0;
570
+ right: 0;
571
+ top: 50%;
572
+ transform: translateY(-50%);
573
+ background-color: var(--primary-color);
574
+ transition: height 0.3s ease;
575
+ }
576
+
577
+ .module-menu .nav-link:hover::before {
578
+ height: 70%;
579
  }
580
+
581
+ .module-menu .nav-link.active::before {
582
+ height: 100%;
583
+ background: linear-gradient(to bottom, var(--accent-color), rgba(255, 177, 0, 0.5));
584
+ animation: pulse-height 1.5s infinite alternate;
585
+ }
586
+
587
+ @keyframes pulse-height {
588
+ 0% { opacity: 0.7; }
589
+ 100% { opacity: 1; }
590
+ }
591
+ </style>
592
+ """
593
+ st.markdown(module_menu_style, unsafe_allow_html=True)
594
+
595
+ # كتلة تحتوي على القائمة مع فئة CSS مخصصة
596
+ menu_container = st.container()
597
+ with menu_container:
598
+ st.markdown('<div class="module-menu">', unsafe_allow_html=True)
599
+
600
+ selected = option_menu.option_menu(
601
+ menu_title=None,
602
+ options=options,
603
+ menu_icon=None,
604
+ default_index=0,
605
+ styles={
606
+ "container": {
607
+ "padding": "0!important",
608
+ "background-color": "transparent",
609
+ "direction": "rtl"
610
+ },
611
+ "icon": {
612
+ "color": "var(--primary-color)",
613
+ "font-size": "1rem",
614
+ "float": "right",
615
+ "margin-left": "12px"
616
+ },
617
+ "nav-link": {
618
+ "font-size": "0.9rem",
619
+ "text-align": "right",
620
+ "direction": "rtl",
621
+ "margin-bottom": "0.35rem",
622
+ "padding": "0.7rem 1rem",
623
+ "border-radius": "6px"
624
+ },
625
+ "nav-link-selected": {
626
+ "background-color": "var(--primary-color)",
627
+ "color": "white",
628
+ "text-align": "right",
629
+ "font-weight": "600"
630
+ },
631
+ }
632
+ )
633
+
634
+ # إغلاق كتلة القائمة
635
+ st.markdown('</div>', unsafe_allow_html=True)
636
 
637
  # تخزين الخيار المحدد
638
  st.session_state[f"{module_name}_selected"] = selected
639
 
640
  return selected
641
 
642
+ # زر للعودة إلى القائمة الرئيسية مع تصميم محسن
643
+ back_button_container = st.container()
644
+ with back_button_container:
645
+ st.markdown(f"""
646
+ <style>
647
+ /* تنسيق زر العودة للقائمة الرئيسية */
648
+ div[data-testid="stButton"][data-testid*="back_btn_{module_name}"] button {{
649
+ background: linear-gradient(135deg, rgba(11, 110, 79, 0.05), rgba(11, 110, 79, 0.1));
650
+ color: var(--primary-color);
651
+ border: 1px solid rgba(11, 110, 79, 0.15);
652
+ padding: 0.7rem;
653
+ border-radius: 8px;
654
+ font-size: 0.95rem;
655
+ font-weight: 500;
656
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
657
+ width: 100%;
658
+ text-align: center;
659
+ margin-top: 1.5rem;
660
+ position: relative;
661
+ overflow: hidden;
662
+ }}
663
+
664
+ div[data-testid="stButton"][data-testid*="back_btn_{module_name}"] button:hover {{
665
+ background: linear-gradient(135deg, rgba(11, 110, 79, 0.1), rgba(11, 110, 79, 0.15));
666
+ border-color: rgba(11, 110, 79, 0.25);
667
+ transform: translateY(-2px);
668
+ box-shadow: 0 4px 12px rgba(11, 110, 79, 0.1);
669
+ }}
670
+
671
+ div[data-testid="stButton"][data-testid*="back_btn_{module_name}"] button:active {{
672
+ transform: translateY(0);
673
+ box-shadow: none;
674
+ }}
675
+
676
+ /* إضافة أيقونة للزر */
677
+ div[data-testid="stButton"][data-testid*="back_btn_{module_name}"] button::before {{
678
+ content: "⟸";
679
+ margin-left: 8px;
680
+ font-size: 1.1rem;
681
+ display: inline-block;
682
+ vertical-align: middle;
683
+ }}
684
+
685
+ /* إضافة تأثير متموج عند النقر */
686
+ @keyframes ripple {{
687
+ 0% {{
688
+ transform: scale(0);
689
+ opacity: 0.5;
690
+ }}
691
+ 100% {{
692
+ transform: scale(4);
693
+ opacity: 0;
694
+ }}
695
+ }}
696
+
697
+ div[data-testid="stButton"][data-testid*="back_btn_{module_name}"] button::after {{
698
+ content: "";
699
+ position: absolute;
700
+ width: 30px;
701
+ height: 30px;
702
+ background: rgba(255, 255, 255, 0.4);
703
+ border-radius: 50%;
704
+ left: 50%;
705
+ top: 50%;
706
+ transform: scale(0);
707
+ transform-origin: center;
708
+ pointer-events: none;
709
+ }}
710
+
711
+ div[data-testid="stButton"][data-testid*="back_btn_{module_name}"] button:active::after {{
712
+ animation: ripple 0.6s ease-out;
713
+ }}
714
+ </style>
715
+ """, unsafe_allow_html=True)
716
+
717
+ # إضافة كتلة على شكل بطاقة تحتوي على الزر
718
+ st.markdown("""
719
+ <div class="back-button-card">
720
+ <style>
721
+ .back-button-card {
722
+ margin-top: 1.5rem;
723
+ margin-bottom: 1rem;
724
+ }
725
+ </style>
726
+ </div>
727
+ """, unsafe_allow_html=True)
728
+
729
+ if st.button("العودة للقائمة الرئيسية", key=f"back_btn_{module_name}"):
730
+ st.session_state["sidebar_selected"] = "الرئيسية"
731
+ st.rerun()
732
 
733
  def get_module_selection(module_name):
734
  """
utils/css/enhanced.css CHANGED
@@ -757,6 +757,8 @@ h1.hero-title::before {
757
  box-shadow: 0 5px 15px rgba(0, 0, 0, 0.05);
758
  transition: transform 0.3s ease, box-shadow 0.3s ease;
759
  text-align: center;
 
 
760
  }
761
 
762
  .service-item:hover {
@@ -764,6 +766,16 @@ h1.hero-title::before {
764
  box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
765
  }
766
 
 
 
 
 
 
 
 
 
 
 
767
  .service-icon {
768
  width: 60px;
769
  height: 60px;
@@ -829,4 +841,346 @@ h1.hero-title::before {
829
  .profile-stats-enhanced {
830
  justify-content: center;
831
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
832
  }
 
757
  box-shadow: 0 5px 15px rgba(0, 0, 0, 0.05);
758
  transition: transform 0.3s ease, box-shadow 0.3s ease;
759
  text-align: center;
760
+ position: relative;
761
+ overflow: hidden;
762
  }
763
 
764
  .service-item:hover {
 
766
  box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
767
  }
768
 
769
+ .service-item::after {
770
+ content: '';
771
+ position: absolute;
772
+ top: 0;
773
+ right: 0;
774
+ width: 100%;
775
+ height: 4px;
776
+ background: linear-gradient(90deg, #1E88E5, #64B5F6);
777
+ }
778
+
779
  .service-icon {
780
  width: 60px;
781
  height: 60px;
 
841
  .profile-stats-enhanced {
842
  justify-content: center;
843
  }
844
+ }
845
+
846
+ /* بطاقات تحليل المناقصات والعقود */
847
+ .tender-card {
848
+ background-color: white;
849
+ border-radius: 15px;
850
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.05);
851
+ margin-bottom: 1.5rem;
852
+ position: relative;
853
+ overflow: hidden;
854
+ transition: transform 0.3s ease, box-shadow 0.3s ease;
855
+ }
856
+
857
+ .tender-card:hover {
858
+ transform: translateY(-5px);
859
+ box-shadow: 0 15px 40px rgba(0, 0, 0, 0.1);
860
+ }
861
+
862
+ .tender-card::before {
863
+ content: '';
864
+ position: absolute;
865
+ top: 0;
866
+ right: 0;
867
+ width: 5px;
868
+ height: 100%;
869
+ background: linear-gradient(180deg, #1E88E5, #64B5F6);
870
+ }
871
+
872
+ .tender-header {
873
+ padding: 1.5rem;
874
+ border-bottom: 1px solid #f0f0f0;
875
+ }
876
+
877
+ .tender-title {
878
+ font-size: 1.4rem;
879
+ font-weight: bold;
880
+ margin-bottom: 0.5rem;
881
+ color: #333;
882
+ }
883
+
884
+ .tender-meta {
885
+ display: flex;
886
+ flex-wrap: wrap;
887
+ gap: 1rem;
888
+ margin-top: 1rem;
889
+ }
890
+
891
+ .tender-meta-item {
892
+ display: flex;
893
+ align-items: center;
894
+ font-size: 0.8rem;
895
+ color: #666;
896
+ }
897
+
898
+ .tender-meta-icon {
899
+ margin-left: 0.5rem;
900
+ color: #1E88E5;
901
+ }
902
+
903
+ .tender-body {
904
+ padding: 1.5rem;
905
+ }
906
+
907
+ .tender-section {
908
+ margin-bottom: 1.5rem;
909
+ }
910
+
911
+ .tender-section-title {
912
+ font-weight: bold;
913
+ margin-bottom: 0.8rem;
914
+ color: #333;
915
+ padding-bottom: 0.5rem;
916
+ border-bottom: 1px solid #f0f0f0;
917
+ }
918
+
919
+ .tender-footer {
920
+ padding: 1rem 1.5rem;
921
+ background-color: #f9fbfe;
922
+ border-top: 1px solid #f0f0f0;
923
+ display: flex;
924
+ justify-content: space-between;
925
+ align-items: center;
926
+ }
927
+
928
+ .tender-actions {
929
+ display: flex;
930
+ gap: 0.8rem;
931
+ }
932
+
933
+ /* تحليل البنود والعناصر */
934
+ .items-table-enhanced {
935
+ width: 100%;
936
+ border-collapse: separate;
937
+ border-spacing: 0;
938
+ margin-bottom: 1.5rem;
939
+ background-color: white;
940
+ border-radius: 10px;
941
+ overflow: hidden;
942
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.05);
943
+ }
944
+
945
+ .items-table-enhanced th {
946
+ background: linear-gradient(135deg, #1E88E5, #1565C0);
947
+ color: white;
948
+ font-weight: bold;
949
+ padding: 1rem;
950
+ text-align: right;
951
+ }
952
+
953
+ .items-table-enhanced td {
954
+ padding: 0.8rem 1rem;
955
+ text-align: right;
956
+ border-bottom: 1px solid #f0f0f0;
957
+ }
958
+
959
+ .items-table-enhanced tr:last-child td {
960
+ border-bottom: none;
961
+ }
962
+
963
+ .items-price {
964
+ font-weight: bold;
965
+ color: #1E88E5;
966
+ }
967
+
968
+ .price-analysis {
969
+ display: flex;
970
+ align-items: center;
971
+ gap: 0.5rem;
972
+ }
973
+
974
+ .price-indicator {
975
+ width: 10px;
976
+ height: 10px;
977
+ border-radius: 50%;
978
+ display: inline-block;
979
+ }
980
+
981
+ .price-indicator-high {
982
+ background-color: #F44336;
983
+ }
984
+
985
+ .price-indicator-normal {
986
+ background-color: #4CAF50;
987
+ }
988
+
989
+ .price-indicator-low {
990
+ background-color: #FFC107;
991
+ }
992
+
993
+ /* تحليل مخاطر العقود */
994
+ .risk-card {
995
+ background-color: white;
996
+ border-radius: 15px;
997
+ padding: 1.5rem;
998
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.05);
999
+ margin-bottom: 1.5rem;
1000
+ position: relative;
1001
+ overflow: hidden;
1002
+ }
1003
+
1004
+ .risk-card::before {
1005
+ content: '';
1006
+ position: absolute;
1007
+ top: 0;
1008
+ right: 0;
1009
+ width: 5px;
1010
+ height: 100%;
1011
+ }
1012
+
1013
+ .risk-card--high::before {
1014
+ background: linear-gradient(180deg, #F44336, #B71C1C);
1015
+ }
1016
+
1017
+ .risk-card--medium::before {
1018
+ background: linear-gradient(180deg, #FFC107, #FFA000);
1019
+ }
1020
+
1021
+ .risk-card--low::before {
1022
+ background: linear-gradient(180deg, #4CAF50, #2E7D32);
1023
+ }
1024
+
1025
+ .risk-header {
1026
+ display: flex;
1027
+ align-items: center;
1028
+ margin-bottom: 1rem;
1029
+ }
1030
+
1031
+ .risk-icon {
1032
+ width: 40px;
1033
+ height: 40px;
1034
+ border-radius: 50%;
1035
+ display: flex;
1036
+ justify-content: center;
1037
+ align-items: center;
1038
+ margin-left: 1rem;
1039
+ color: white;
1040
+ }
1041
+
1042
+ .risk-icon--high {
1043
+ background: linear-gradient(135deg, #F44336, #B71C1C);
1044
+ }
1045
+
1046
+ .risk-icon--medium {
1047
+ background: linear-gradient(135deg, #FFC107, #FFA000);
1048
+ }
1049
+
1050
+ .risk-icon--low {
1051
+ background: linear-gradient(135deg, #4CAF50, #2E7D32);
1052
+ }
1053
+
1054
+ .risk-title {
1055
+ font-weight: bold;
1056
+ color: #333;
1057
+ }
1058
+
1059
+ .risk-description {
1060
+ margin-bottom: 1rem;
1061
+ color: #666;
1062
+ }
1063
+
1064
+ .risk-actions {
1065
+ display: flex;
1066
+ gap: 0.8rem;
1067
+ margin-top: 1rem;
1068
+ }
1069
+
1070
+ /* دليل التحليل والتصنيف */
1071
+ .legend-card {
1072
+ background-color: white;
1073
+ border-radius: 10px;
1074
+ padding: 1.2rem;
1075
+ box-shadow: 0 5px 15px rgba(0, 0, 0, 0.05);
1076
+ margin-bottom: 1.5rem;
1077
+ }
1078
+
1079
+ .legend-title {
1080
+ font-weight: bold;
1081
+ margin-bottom: 1rem;
1082
+ color: #333;
1083
+ padding-bottom: 0.5rem;
1084
+ border-bottom: 1px solid #f0f0f0;
1085
+ }
1086
+
1087
+ .legend-items {
1088
+ display: flex;
1089
+ flex-wrap: wrap;
1090
+ gap: 1rem;
1091
+ }
1092
+
1093
+ .legend-item {
1094
+ display: flex;
1095
+ align-items: center;
1096
+ margin-bottom: 0.8rem;
1097
+ }
1098
+
1099
+ .legend-color {
1100
+ width: 16px;
1101
+ height: 16px;
1102
+ border-radius: 4px;
1103
+ margin-left: 0.5rem;
1104
+ }
1105
+
1106
+ .legend-label {
1107
+ font-size: 0.9rem;
1108
+ color: #333;
1109
+ }
1110
+
1111
+ /* النماذج والاستمارات */
1112
+ .form-enhanced {
1113
+ background-color: white;
1114
+ border-radius: 15px;
1115
+ padding: 1.5rem;
1116
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.05);
1117
+ margin-bottom: 1.5rem;
1118
+ }
1119
+
1120
+ .form-title {
1121
+ font-size: 1.4rem;
1122
+ font-weight: bold;
1123
+ margin-bottom: 1.5rem;
1124
+ color: #333;
1125
+ text-align: center;
1126
+ }
1127
+
1128
+ .form-section {
1129
+ margin-bottom: 1.5rem;
1130
+ }
1131
+
1132
+ .form-section-title {
1133
+ font-weight: bold;
1134
+ margin-bottom: 1rem;
1135
+ color: #333;
1136
+ padding-bottom: 0.5rem;
1137
+ border-bottom: 1px solid #f0f0f0;
1138
+ }
1139
+
1140
+ .form-row {
1141
+ display: flex;
1142
+ gap: 1rem;
1143
+ margin-bottom: 1rem;
1144
+ }
1145
+
1146
+ .form-group {
1147
+ flex: 1;
1148
+ }
1149
+
1150
+ .form-label {
1151
+ display: block;
1152
+ margin-bottom: 0.5rem;
1153
+ font-weight: 500;
1154
+ color: #333;
1155
+ }
1156
+
1157
+ .form-input,
1158
+ .form-select,
1159
+ .form-textarea {
1160
+ width: 100%;
1161
+ padding: 0.8rem 1rem;
1162
+ border: 1px solid #ddd;
1163
+ border-radius: 5px;
1164
+ font-size: 1rem;
1165
+ transition: border-color 0.3s ease, box-shadow 0.3s ease;
1166
+ }
1167
+
1168
+ .form-input:focus,
1169
+ .form-select:focus,
1170
+ .form-textarea:focus {
1171
+ border-color: #1E88E5;
1172
+ box-shadow: 0 0 0 3px rgba(30, 136, 229, 0.2);
1173
+ outline: none;
1174
+ }
1175
+
1176
+ .form-textarea {
1177
+ min-height: 100px;
1178
+ resize: vertical;
1179
+ }
1180
+
1181
+ .form-actions {
1182
+ display: flex;
1183
+ justify-content: flex-end;
1184
+ gap: 1rem;
1185
+ margin-top: 1.5rem;
1186
  }
utils/css/main.css CHANGED
@@ -6,39 +6,114 @@
6
  /* ================= المتغيرات العامة ================= */
7
  :root {
8
  /* الألوان الرئيسية */
9
- --primary-color: #1E88E5;
10
- --primary-light: #64B5F6;
11
- --primary-dark: #1565C0;
12
- --secondary-color: #E3F2FD;
 
 
 
 
 
 
13
 
14
- /* ألوان مخصصة */
15
- --success-color: #4CAF50;
16
- --success-light: #81C784;
17
- --warning-color: #FFC107;
18
- --warning-light: #FFD54F;
19
- --danger-color: #F44336;
20
- --danger-light: #E57373;
21
- --info-color: #2196F3;
22
- --info-light: #64B5F6;
 
 
 
 
23
 
24
- /* ألوان محايدة */
25
- --gray-100: #f8f9fa;
26
- --gray-200: #f0f2f5;
27
- --gray-300: #dee2e6;
28
- --gray-400: #ced4da;
29
- --gray-500: #adb5bd;
30
- --gray-600: #6c757d;
31
- --gray-700: #495057;
32
- --gray-800: #343a40;
33
- --gray-900: #212529;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
 
35
  /* خصائص الخط */
36
  --font-family: 'Tajawal', 'Cairo', sans-serif;
37
  --font-size-base: 16px;
 
38
  --font-size-sm: 0.875rem;
 
39
  --font-size-lg: 1.125rem;
40
- --font-size-xl: 1.5rem;
41
- --font-size-2xl: 2rem;
 
 
 
 
 
 
 
 
 
 
42
 
43
  /* المسافات */
44
  --spacing-xs: 0.25rem;
@@ -47,6 +122,7 @@
47
  --spacing-lg: 1.5rem;
48
  --spacing-xl: 2rem;
49
  --spacing-2xl: 3rem;
 
50
 
51
  /* الظلال */
52
  --shadow-sm: 0 2px 4px rgba(0, 0, 0, 0.05);
@@ -54,13 +130,55 @@
54
  --shadow-md: 0 6px 10px rgba(0, 0, 0, 0.1);
55
  --shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.1);
56
  --shadow-xl: 0 15px 20px rgba(0, 0, 0, 0.1);
 
 
 
 
 
57
 
58
  /* الحدود المستديرة */
59
- --border-radius-sm: 0.25rem;
60
- --border-radius: 0.5rem;
61
- --border-radius-lg: 0.75rem;
62
- --border-radius-xl: 1rem;
 
 
63
  --border-radius-circle: 50%;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
  }
65
 
66
  /* ================= أساسيات النمط ================= */
@@ -319,17 +437,17 @@ img {
319
  }
320
 
321
  .alert-success {
322
- background-color: #E8F5E9;
323
  border-right: 4px solid var(--success-color);
324
  }
325
 
326
  .alert-warning {
327
- background-color: #FFF8E1;
328
  border-right: 4px solid var(--warning-color);
329
  }
330
 
331
  .alert-danger {
332
- background-color: #FFEBEE;
333
  border-right: 4px solid var(--danger-color);
334
  }
335
 
@@ -609,12 +727,34 @@ img {
609
  padding: var(--spacing-lg);
610
  box-shadow: var(--shadow);
611
  margin-bottom: var(--spacing-lg);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
612
  }
613
 
614
  .chart-title {
615
  font-size: var(--font-size-lg);
616
- font-weight: 700;
617
  margin-bottom: var(--spacing-sm);
 
 
 
618
  text-align: center;
619
  }
620
 
@@ -622,6 +762,160 @@ img {
622
  color: var(--gray-600);
623
  margin-bottom: var(--spacing-md);
624
  text-align: center;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
625
  }
626
 
627
  /* عناصر تصميم خريطة المشروع */
@@ -690,6 +984,413 @@ img {
690
  margin: 0 auto var(--spacing-lg);
691
  }
692
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
693
  /* ================= تطبيق الاستجابة لمختلف الأجهزة ================= */
694
  @media screen and (max-width: 992px) {
695
  :root {
@@ -704,6 +1405,20 @@ img {
704
  .header-nav {
705
  margin-top: var(--spacing-md);
706
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
707
  }
708
 
709
  @media screen and (max-width: 768px) {
@@ -720,6 +1435,28 @@ img {
720
  flex-direction: column;
721
  align-items: flex-start;
722
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
723
  }
724
 
725
  @media screen and (max-width: 576px) {
@@ -731,4 +1468,9 @@ img {
731
  .detail-actions {
732
  margin-top: var(--spacing-md);
733
  }
 
 
 
 
 
734
  }
 
6
  /* ================= المتغيرات العامة ================= */
7
  :root {
8
  /* الألوان الرئيسية */
9
+ --primary-color: #0B6E4F;
10
+ --primary-light: #08875D;
11
+ --primary-dark: #085F45;
12
+ --secondary-color: #E8F5F0;
13
+ --accent-color: #FFB100;
14
+ --accent-light: #FFCB52;
15
+ --accent-dark: #E69D00;
16
+ --tertiary-color: #5754FF;
17
+ --tertiary-light: #7A78FF;
18
+ --tertiary-dark: #4240D4;
19
 
20
+ /* ألوان حالات التطبيق */
21
+ --success-color: #10B981;
22
+ --success-light: #D1FAE5;
23
+ --success-dark: #059669;
24
+ --warning-color: #F59E0B;
25
+ --warning-light: #FEF3C7;
26
+ --warning-dark: #D97706;
27
+ --danger-color: #EF4444;
28
+ --danger-light: #FEE2E2;
29
+ --danger-dark: #DC2626;
30
+ --info-color: #3B82F6;
31
+ --info-light: #DBEAFE;
32
+ --info-dark: #2563EB;
33
 
34
+ /* التدرجات اللونية */
35
+ --primary-gradient: linear-gradient(135deg, #0B6E4F 0%, #08875D 100%);
36
+ --success-gradient: linear-gradient(135deg, #10B981 0%, #059669 100%);
37
+ --danger-gradient: linear-gradient(135deg, #EF4444 0%, #DC2626 100%);
38
+ --warning-gradient: linear-gradient(135deg, #F59E0B 0%, #D97706 100%);
39
+ --info-gradient: linear-gradient(135deg, #3B82F6 0%, #2563EB 100%);
40
+ --accent-gradient: linear-gradient(135deg, #FFB100 0%, #E69D00 100%);
41
+ --tertiary-gradient: linear-gradient(135deg, #5754FF 0%, #4240D4 100%);
42
+ --glass-gradient: linear-gradient(135deg, rgba(255, 255, 255, 0.5) 0%, rgba(255, 255, 255, 0.2) 100%);
43
+
44
+ /* ألوان RGB للاستخدام في الشفافية */
45
+ --primary-color-rgb: 11, 110, 79;
46
+ --primary-light-rgb: 8, 135, 93;
47
+ --primary-dark-rgb: 8, 95, 69;
48
+ --secondary-color-rgb: 232, 245, 240;
49
+ --accent-color-rgb: 255, 177, 0;
50
+ --accent-light-rgb: 255, 203, 82;
51
+ --accent-dark-rgb: 230, 157, 0;
52
+ --tertiary-color-rgb: 87, 84, 255;
53
+ --tertiary-light-rgb: 122, 120, 255;
54
+ --tertiary-dark-rgb: 66, 64, 212;
55
+ --success-color-rgb: 16, 185, 129;
56
+ --success-light-rgb: 209, 250, 229;
57
+ --success-dark-rgb: 5, 150, 105;
58
+ --warning-color-rgb: 245, 158, 11;
59
+ --warning-light-rgb: 254, 243, 199;
60
+ --warning-dark-rgb: 217, 119, 6;
61
+ --danger-color-rgb: 239, 68, 68;
62
+ --danger-light-rgb: 254, 226, 226;
63
+ --danger-dark-rgb: 220, 38, 38;
64
+ --info-color-rgb: 59, 130, 246;
65
+ --info-light-rgb: 219, 234, 254;
66
+ --info-dark-rgb: 37, 99, 235;
67
+
68
+ /* ألوان محددة لمختلف الأقسام */
69
+ --pricing-color: #0B6E4F;
70
+ --pricing-color-rgb: 11, 110, 79;
71
+ --contract-color: #10B981;
72
+ --contract-color-rgb: 16, 185, 129;
73
+ --risk-color: #EF4444;
74
+ --risk-color-rgb: 239, 68, 68;
75
+ --map-color: #F59E0B;
76
+ --map-color-rgb: 245, 158, 11;
77
+ --notification-color: #5754FF;
78
+ --notification-color-rgb: 87, 84, 255;
79
+ --tracker-color: #08875D;
80
+ --tracker-color-rgb: 8, 135, 93;
81
+ --resources-color: #FFB100;
82
+ --resources-color-rgb: 255, 177, 0;
83
+ --assistant-color: #5754FF;
84
+ --assistant-color-rgb: 87, 84, 255;
85
+
86
+ /* ألوان التدرج الرمادي */
87
+ --gray-50: #f9fafb;
88
+ --gray-100: #f3f4f6;
89
+ --gray-200: #e5e7eb;
90
+ --gray-300: #d1d5db;
91
+ --gray-400: #9ca3af;
92
+ --gray-500: #6b7280;
93
+ --gray-600: #4b5563;
94
+ --gray-700: #374151;
95
+ --gray-800: #1f2937;
96
+ --gray-900: #111827;
97
 
98
  /* خصائص الخط */
99
  --font-family: 'Tajawal', 'Cairo', sans-serif;
100
  --font-size-base: 16px;
101
+ --font-size-xs: 0.75rem;
102
  --font-size-sm: 0.875rem;
103
+ --font-size-md: 1rem;
104
  --font-size-lg: 1.125rem;
105
+ --font-size-xl: 1.25rem;
106
+ --font-size-2xl: 1.5rem;
107
+ --font-size-3xl: 1.875rem;
108
+ --font-size-4xl: 2.25rem;
109
+ --font-size-5xl: 3rem;
110
+
111
+ /* أوزان الخط */
112
+ --font-weight-normal: 400;
113
+ --font-weight-medium: 500;
114
+ --font-weight-semibold: 600;
115
+ --font-weight-bold: 700;
116
+ --font-weight-extrabold: 800;
117
 
118
  /* المسافات */
119
  --spacing-xs: 0.25rem;
 
122
  --spacing-lg: 1.5rem;
123
  --spacing-xl: 2rem;
124
  --spacing-2xl: 3rem;
125
+ --spacing-3xl: 4rem;
126
 
127
  /* الظلال */
128
  --shadow-sm: 0 2px 4px rgba(0, 0, 0, 0.05);
 
130
  --shadow-md: 0 6px 10px rgba(0, 0, 0, 0.1);
131
  --shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.1);
132
  --shadow-xl: 0 15px 20px rgba(0, 0, 0, 0.1);
133
+ --shadow-card: 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 2px rgba(0, 0, 0, 0.1);
134
+ --shadow-hover: 0 8px 15px rgba(0, 0, 0, 0.1);
135
+ --shadow-colored-sm: 0 2px 4px rgba(11, 110, 79, 0.1);
136
+ --shadow-colored-md: 0 6px 12px rgba(11, 110, 79, 0.15);
137
+ --shadow-inset: inset 0 2px 4px rgba(0, 0, 0, 0.05);
138
 
139
  /* الحدود المستديرة */
140
+ --border-radius-xs: 2px;
141
+ --border-radius-sm: 4px;
142
+ --border-radius: 8px;
143
+ --border-radius-lg: 12px;
144
+ --border-radius-xl: 16px;
145
+ --border-radius-2xl: 24px;
146
  --border-radius-circle: 50%;
147
+ --border-radius-pill: 9999px;
148
+
149
+ /* حدود العناصر */
150
+ --border-width: 1px;
151
+ --border-width-md: 2px;
152
+ --border-width-lg: 3px;
153
+ --border-color: var(--gray-200);
154
+ --border-color-dark: var(--gray-300);
155
+
156
+ /* التحولات والتأثيرات */
157
+ --transition-fast: 150ms;
158
+ --transition-normal: 300ms;
159
+ --transition-slow: 500ms;
160
+ --transition-property: all;
161
+ --transition-timing: cubic-bezier(0.4, 0, 0.2, 1);
162
+
163
+ /* تأثيرات متنوعة */
164
+ --blur-sm: blur(4px);
165
+ --blur-md: blur(8px);
166
+ --blur-lg: blur(16px);
167
+ --backdrop-blur: blur(10px);
168
+
169
+ /* مسافات متباعدة */
170
+ --letter-spacing-tight: -0.025em;
171
+ --letter-spacing-normal: 0em;
172
+ --letter-spacing-wide: 0.025em;
173
+
174
+ /* حجم الخط حسب الموضوع */
175
+ --heading-line-height: 1.2;
176
+ --body-line-height: 1.5;
177
+
178
+ /* تنسيقات طباعة عامة لأجزاء مختلفة من الواجهة */
179
+ --container-padding: var(--spacing-lg);
180
+ --section-spacing: var(--spacing-xl);
181
+ --card-padding: var(--spacing-lg);
182
  }
183
 
184
  /* ================= أساسيات النمط ================= */
 
437
  }
438
 
439
  .alert-success {
440
+ background-color: var(--success-light);
441
  border-right: 4px solid var(--success-color);
442
  }
443
 
444
  .alert-warning {
445
+ background-color: var(--warning-light);
446
  border-right: 4px solid var(--warning-color);
447
  }
448
 
449
  .alert-danger {
450
+ background-color: var(--danger-light);
451
  border-right: 4px solid var(--danger-color);
452
  }
453
 
 
727
  padding: var(--spacing-lg);
728
  box-shadow: var(--shadow);
729
  margin-bottom: var(--spacing-lg);
730
+ position: relative;
731
+ overflow: hidden;
732
+ transition: all var(--transition-normal) var(--transition-timing);
733
+ }
734
+
735
+ .chart-container:hover {
736
+ box-shadow: var(--shadow-lg);
737
+ transform: translateY(-2px);
738
+ }
739
+
740
+ .chart-container::after {
741
+ content: '';
742
+ position: absolute;
743
+ top: 0;
744
+ right: 0;
745
+ width: 4px;
746
+ height: 100%;
747
+ background: var(--primary-gradient);
748
+ opacity: 0.7;
749
  }
750
 
751
  .chart-title {
752
  font-size: var(--font-size-lg);
753
+ font-weight: var(--font-weight-bold);
754
  margin-bottom: var(--spacing-sm);
755
+ color: var(--gray-900);
756
+ border-bottom: 1px solid var(--gray-200);
757
+ padding-bottom: var(--spacing-sm);
758
  text-align: center;
759
  }
760
 
 
762
  color: var(--gray-600);
763
  margin-bottom: var(--spacing-md);
764
  text-align: center;
765
+ font-size: var(--font-size-sm);
766
+ }
767
+
768
+ .chart-controls {
769
+ display: flex;
770
+ justify-content: space-between;
771
+ align-items: center;
772
+ margin-bottom: var(--spacing-md);
773
+ }
774
+
775
+ .chart-legend {
776
+ display: flex;
777
+ flex-wrap: wrap;
778
+ justify-content: center;
779
+ gap: var(--spacing-sm);
780
+ margin-top: var(--spacing-md);
781
+ }
782
+
783
+ .chart-legend-item {
784
+ display: flex;
785
+ align-items: center;
786
+ margin-left: var(--spacing-sm);
787
+ }
788
+
789
+ .chart-legend-color {
790
+ width: 12px;
791
+ height: 12px;
792
+ border-radius: var(--border-radius-sm);
793
+ margin-left: var(--spacing-xs);
794
+ }
795
+
796
+ .chart-legend-label {
797
+ font-size: var(--font-size-xs);
798
+ color: var(--gray-700);
799
+ }
800
+
801
+ .chart-tooltip {
802
+ background-color: rgba(0, 0, 0, 0.8);
803
+ color: white;
804
+ padding: var(--spacing-sm);
805
+ border-radius: var(--border-radius-sm);
806
+ font-size: var(--font-size-xs);
807
+ max-width: 200px;
808
+ z-index: 10;
809
+ }
810
+
811
+ .chart-grid {
812
+ display: grid;
813
+ grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
814
+ gap: var(--spacing-lg);
815
+ }
816
+
817
+ .chart-tabs {
818
+ display: flex;
819
+ border-bottom: 1px solid var(--gray-200);
820
+ margin-bottom: var(--spacing-md);
821
+ }
822
+
823
+ .chart-tab {
824
+ padding: var(--spacing-sm) var(--spacing-md);
825
+ cursor: pointer;
826
+ transition: all var(--transition-normal);
827
+ font-size: var(--font-size-sm);
828
+ color: var(--gray-600);
829
+ border-bottom: 2px solid transparent;
830
+ }
831
+
832
+ .chart-tab:hover {
833
+ color: var(--primary-color);
834
+ }
835
+
836
+ .chart-tab.active {
837
+ color: var(--primary-color);
838
+ border-bottom-color: var(--primary-color);
839
+ font-weight: var(--font-weight-medium);
840
+ }
841
+
842
+ .chart-statistics {
843
+ display: flex;
844
+ justify-content: space-evenly;
845
+ margin-bottom: var(--spacing-md);
846
+ }
847
+
848
+ .chart-statistic {
849
+ text-align: center;
850
+ padding: var(--spacing-sm);
851
+ }
852
+
853
+ .chart-statistic-value {
854
+ font-size: var(--font-size-2xl);
855
+ font-weight: var(--font-weight-bold);
856
+ color: var(--primary-color);
857
+ margin-bottom: var(--spacing-xs);
858
+ }
859
+
860
+ .chart-statistic-label {
861
+ font-size: var(--font-size-xs);
862
+ color: var(--gray-600);
863
+ }
864
+
865
+ .chart-overlay {
866
+ position: absolute;
867
+ top: 0;
868
+ left: 0;
869
+ width: 100%;
870
+ height: 100%;
871
+ background-color: rgba(255, 255, 255, 0.7);
872
+ display: flex;
873
+ align-items: center;
874
+ justify-content: center;
875
+ z-index: 2;
876
+ }
877
+
878
+ .chart-empty {
879
+ text-align: center;
880
+ padding: var(--spacing-lg);
881
+ color: var(--gray-500);
882
+ }
883
+
884
+ .chart-loading {
885
+ width: 40px;
886
+ height: 40px;
887
+ border: 3px solid var(--gray-200);
888
+ border-top-color: var(--primary-color);
889
+ border-radius: 50%;
890
+ animation: chart-loading-spin 1s linear infinite;
891
+ }
892
+
893
+ @keyframes chart-loading-spin {
894
+ to {
895
+ transform: rotate(360deg);
896
+ }
897
+ }
898
+
899
+ .chart-mini {
900
+ height: 100px;
901
+ margin-bottom: var(--spacing-sm);
902
+ }
903
+
904
+ .chart-mini .chart-title {
905
+ font-size: var(--font-size-sm);
906
+ margin-bottom: var(--spacing-xs);
907
+ text-align: right;
908
+ padding-bottom: var(--spacing-xs);
909
+ }
910
+
911
+ .chart-card {
912
+ background: white;
913
+ border-radius: var(--border-radius);
914
+ box-shadow: var(--shadow-card);
915
+ padding: var(--spacing-md);
916
+ margin-bottom: var(--spacing-md);
917
+ position: relative;
918
+ overflow: hidden;
919
  }
920
 
921
  /* عناصر تصميم خريطة المشروع */
 
984
  margin: 0 auto var(--spacing-lg);
985
  }
986
 
987
+ /* ================= مكونات واجهة المستخدم المتقدمة ================= */
988
+
989
+ /* بطاقات عرض عمليات الحساب والتحليل */
990
+ .calculation-card {
991
+ background-color: white;
992
+ border-radius: var(--border-radius);
993
+ padding: var(--spacing-lg);
994
+ box-shadow: var(--shadow-card);
995
+ margin-bottom: var(--spacing-lg);
996
+ position: relative;
997
+ border-right: var(--border-width-lg) solid var(--primary-color);
998
+ }
999
+
1000
+ .calculation-header {
1001
+ display: flex;
1002
+ justify-content: space-between;
1003
+ align-items: center;
1004
+ margin-bottom: var(--spacing-md);
1005
+ padding-bottom: var(--spacing-md);
1006
+ border-bottom: 1px solid var(--border-color);
1007
+ }
1008
+
1009
+ .calculation-title {
1010
+ font-size: var(--font-size-lg);
1011
+ font-weight: var(--font-weight-bold);
1012
+ color: var(--gray-800);
1013
+ }
1014
+
1015
+ .calculation-controls {
1016
+ display: flex;
1017
+ gap: var(--spacing-sm);
1018
+ }
1019
+
1020
+ .calculation-control-button {
1021
+ background-color: var(--gray-100);
1022
+ border: none;
1023
+ border-radius: var(--border-radius-sm);
1024
+ padding: var(--spacing-xs) var(--spacing-sm);
1025
+ color: var(--gray-700);
1026
+ cursor: pointer;
1027
+ transition: background-color var(--transition-normal);
1028
+ }
1029
+
1030
+ .calculation-control-button:hover {
1031
+ background-color: var(--gray-200);
1032
+ }
1033
+
1034
+ .calculation-content {
1035
+ margin-bottom: var(--spacing-md);
1036
+ }
1037
+
1038
+ .calculation-formula {
1039
+ font-family: monospace;
1040
+ background-color: var(--gray-100);
1041
+ padding: var(--spacing-md);
1042
+ border-radius: var(--border-radius-sm);
1043
+ margin-bottom: var(--spacing-md);
1044
+ white-space: pre-wrap;
1045
+ color: var(--gray-800);
1046
+ direction: ltr; /* للصيغ الرياضية */
1047
+ text-align: left;
1048
+ }
1049
+
1050
+ .calculation-result {
1051
+ font-weight: var(--font-weight-bold);
1052
+ color: var(--primary-color);
1053
+ font-size: var(--font-size-lg);
1054
+ padding: var(--spacing-md);
1055
+ background-color: var(--secondary-color);
1056
+ border-radius: var(--border-radius-sm);
1057
+ }
1058
+
1059
+ /* بطاقات الذكاء الاصطناعي والتحليل الذكي */
1060
+ .ai-insight-card {
1061
+ background-color: white;
1062
+ border-radius: var(--border-radius);
1063
+ padding: var(--spacing-lg);
1064
+ box-shadow: var(--shadow-card);
1065
+ margin-bottom: var(--spacing-lg);
1066
+ position: relative;
1067
+ border-right: var(--border-width-lg) solid var(--tertiary-color);
1068
+ }
1069
+
1070
+ .ai-insight-header {
1071
+ display: flex;
1072
+ align-items: center;
1073
+ margin-bottom: var(--spacing-md);
1074
+ }
1075
+
1076
+ .ai-insight-icon {
1077
+ width: 32px;
1078
+ height: 32px;
1079
+ background-color: var(--tertiary-light);
1080
+ border-radius: var(--border-radius-circle);
1081
+ display: flex;
1082
+ align-items: center;
1083
+ justify-content: center;
1084
+ margin-left: var(--spacing-md);
1085
+ color: white;
1086
+ }
1087
+
1088
+ .ai-insight-title {
1089
+ font-size: var(--font-size-lg);
1090
+ font-weight: var(--font-weight-bold);
1091
+ color: var(--tertiary-color);
1092
+ }
1093
+
1094
+ .ai-insight-content {
1095
+ padding: var(--spacing-md);
1096
+ border-right: 3px solid var(--tertiary-color);
1097
+ margin-bottom: var(--spacing-md);
1098
+ background-color: var(--gray-50);
1099
+ border-radius: var(--border-radius-sm);
1100
+ }
1101
+
1102
+ .ai-insight-tag {
1103
+ display: inline-block;
1104
+ background-color: var(--tertiary-light);
1105
+ color: white;
1106
+ font-size: var(--font-size-xs);
1107
+ padding: 2px var(--spacing-sm);
1108
+ border-radius: var(--border-radius-pill);
1109
+ margin-left: var(--spacing-sm);
1110
+ margin-bottom: var(--spacing-sm);
1111
+ }
1112
+
1113
+ /* محادثة الذكاء الاصطناعي */
1114
+ .ai-chat-container {
1115
+ background-color: white;
1116
+ border-radius: var(--border-radius);
1117
+ box-shadow: var(--shadow-card);
1118
+ margin-bottom: var(--spacing-lg);
1119
+ max-height: 600px;
1120
+ display: flex;
1121
+ flex-direction: column;
1122
+ }
1123
+
1124
+ .ai-chat-header {
1125
+ padding: var(--spacing-md);
1126
+ border-bottom: 1px solid var(--border-color);
1127
+ display: flex;
1128
+ align-items: center;
1129
+ }
1130
+
1131
+ .ai-chat-title {
1132
+ font-weight: var(--font-weight-semibold);
1133
+ color: var(--gray-800);
1134
+ margin: 0;
1135
+ }
1136
+
1137
+ .ai-chat-messages {
1138
+ padding: var(--spacing-md);
1139
+ overflow-y: auto;
1140
+ flex: 1;
1141
+ }
1142
+
1143
+ .ai-message {
1144
+ display: flex;
1145
+ margin-bottom: var(--spacing-md);
1146
+ }
1147
+
1148
+ .ai-message-avatar {
1149
+ width: 36px;
1150
+ height: 36px;
1151
+ border-radius: var(--border-radius-circle);
1152
+ background-color: var(--tertiary-color);
1153
+ display: flex;
1154
+ align-items: center;
1155
+ justify-content: center;
1156
+ color: white;
1157
+ margin-left: var(--spacing-md);
1158
+ font-size: var(--font-size-xs);
1159
+ flex-shrink: 0;
1160
+ }
1161
+
1162
+ .user-message-avatar {
1163
+ width: 36px;
1164
+ height: 36px;
1165
+ border-radius: var(--border-radius-circle);
1166
+ background-color: var(--primary-color);
1167
+ display: flex;
1168
+ align-items: center;
1169
+ justify-content: center;
1170
+ color: white;
1171
+ margin-left: var(--spacing-md);
1172
+ font-size: var(--font-size-xs);
1173
+ flex-shrink: 0;
1174
+ }
1175
+
1176
+ .ai-message-content {
1177
+ background-color: var(--gray-100);
1178
+ padding: var(--spacing-md);
1179
+ border-radius: var(--border-radius);
1180
+ max-width: 80%;
1181
+ border-top-right-radius: 0;
1182
+ }
1183
+
1184
+ .user-message-content {
1185
+ background-color: var(--primary-light);
1186
+ color: white;
1187
+ padding: var(--spacing-md);
1188
+ border-radius: var(--border-radius);
1189
+ max-width: 80%;
1190
+ border-top-right-radius: 0;
1191
+ }
1192
+
1193
+ .ai-chat-footer {
1194
+ padding: var(--spacing-md);
1195
+ border-top: 1px solid var(--border-color);
1196
+ display: flex;
1197
+ }
1198
+
1199
+ .ai-chat-input {
1200
+ flex: 1;
1201
+ padding: var(--spacing-sm) var(--spacing-md);
1202
+ border: 1px solid var(--border-color);
1203
+ border-radius: var(--border-radius-pill);
1204
+ margin-left: var(--spacing-sm);
1205
+ }
1206
+
1207
+ .ai-chat-send {
1208
+ background-color: var(--primary-color);
1209
+ color: white;
1210
+ border: none;
1211
+ border-radius: var(--border-radius-pill);
1212
+ padding: var(--spacing-sm) var(--spacing-md);
1213
+ cursor: pointer;
1214
+ }
1215
+
1216
+ /* بطاقات المشاريع المحسنة */
1217
+ .project-card-enhanced {
1218
+ background-color: white;
1219
+ border-radius: var(--border-radius);
1220
+ box-shadow: var(--shadow-card);
1221
+ margin-bottom: var(--spacing-lg);
1222
+ position: relative;
1223
+ overflow: hidden;
1224
+ }
1225
+
1226
+ .project-card-header {
1227
+ padding: var(--spacing-lg);
1228
+ background: var(--primary-gradient);
1229
+ color: white;
1230
+ }
1231
+
1232
+ .project-card-title {
1233
+ font-size: var(--font-size-xl);
1234
+ font-weight: var(--font-weight-bold);
1235
+ margin-bottom: var(--spacing-xs);
1236
+ }
1237
+
1238
+ .project-card-subtitle {
1239
+ font-size: var(--font-size-sm);
1240
+ opacity: 0.9;
1241
+ }
1242
+
1243
+ .project-card-body {
1244
+ padding: var(--spacing-lg);
1245
+ }
1246
+
1247
+ .project-card-stats {
1248
+ display: flex;
1249
+ gap: var(--spacing-md);
1250
+ margin-bottom: var(--spacing-md);
1251
+ }
1252
+
1253
+ .project-card-stat {
1254
+ flex: 1;
1255
+ text-align: center;
1256
+ padding: var(--spacing-sm);
1257
+ background-color: var(--gray-50);
1258
+ border-radius: var(--border-radius-sm);
1259
+ }
1260
+
1261
+ .project-card-stat-value {
1262
+ font-size: var(--font-size-xl);
1263
+ font-weight: var(--font-weight-bold);
1264
+ color: var(--primary-color);
1265
+ }
1266
+
1267
+ .project-card-stat-label {
1268
+ font-size: var(--font-size-xs);
1269
+ color: var(--gray-600);
1270
+ }
1271
+
1272
+ .project-card-content {
1273
+ margin-bottom: var(--spacing-md);
1274
+ }
1275
+
1276
+ .project-card-footer {
1277
+ border-top: 1px solid var(--border-color);
1278
+ padding-top: var(--spacing-md);
1279
+ display: flex;
1280
+ justify-content: space-between;
1281
+ align-items: center;
1282
+ }
1283
+
1284
+ .project-tag {
1285
+ display: inline-block;
1286
+ background-color: var(--primary-light);
1287
+ color: white;
1288
+ font-size: var(--font-size-xs);
1289
+ padding: 2px var(--spacing-sm);
1290
+ border-radius: var(--border-radius-pill);
1291
+ margin-left: var(--spacing-sm);
1292
+ margin-bottom: var(--spacing-sm);
1293
+ }
1294
+
1295
+ /* تصميم المخططات الزمنية */
1296
+ .timeline-container {
1297
+ padding: var(--spacing-lg);
1298
+ position: relative;
1299
+ }
1300
+
1301
+ .timeline-line {
1302
+ position: absolute;
1303
+ top: 0;
1304
+ right: 50px;
1305
+ width: 4px;
1306
+ height: 100%;
1307
+ background-color: var(--gray-200);
1308
+ }
1309
+
1310
+ .timeline-item {
1311
+ display: flex;
1312
+ margin-bottom: var(--spacing-xl);
1313
+ position: relative;
1314
+ }
1315
+
1316
+ .timeline-icon {
1317
+ width: 40px;
1318
+ height: 40px;
1319
+ background-color: var(--primary-color);
1320
+ border-radius: var(--border-radius-circle);
1321
+ display: flex;
1322
+ align-items: center;
1323
+ justify-content: center;
1324
+ color: white;
1325
+ margin-left: var(--spacing-lg);
1326
+ z-index: 1;
1327
+ position: relative;
1328
+ }
1329
+
1330
+ .timeline-content {
1331
+ background-color: white;
1332
+ padding: var(--spacing-md);
1333
+ border-radius: var(--border-radius);
1334
+ box-shadow: var(--shadow-card);
1335
+ flex: 1;
1336
+ }
1337
+
1338
+ .timeline-date {
1339
+ font-size: var(--font-size-sm);
1340
+ color: var(--gray-600);
1341
+ margin-bottom: var(--spacing-xs);
1342
+ }
1343
+
1344
+ .timeline-title {
1345
+ font-weight: var(--font-weight-bold);
1346
+ color: var(--gray-800);
1347
+ margin-bottom: var(--spacing-xs);
1348
+ }
1349
+
1350
+ .timeline-description {
1351
+ color: var(--gray-700);
1352
+ }
1353
+
1354
+ /* واجهة المساعد الذكي */
1355
+ .assistant-container {
1356
+ display: flex;
1357
+ gap: var(--spacing-lg);
1358
+ margin-bottom: var(--spacing-lg);
1359
+ }
1360
+
1361
+ .assistant-sidebar {
1362
+ width: 280px;
1363
+ background-color: white;
1364
+ border-radius: var(--border-radius);
1365
+ box-shadow: var(--shadow-card);
1366
+ padding: var(--spacing-md);
1367
+ }
1368
+
1369
+ .assistant-main {
1370
+ flex: 1;
1371
+ background-color: white;
1372
+ border-radius: var(--border-radius);
1373
+ box-shadow: var(--shadow-card);
1374
+ padding: var(--spacing-md);
1375
+ }
1376
+
1377
+ .assistant-history-item {
1378
+ padding: var(--spacing-sm);
1379
+ margin-bottom: var(--spacing-sm);
1380
+ border-radius: var(--border-radius-sm);
1381
+ cursor: pointer;
1382
+ transition: background-color var(--transition-normal);
1383
+ }
1384
+
1385
+ .assistant-history-item:hover {
1386
+ background-color: var(--gray-100);
1387
+ }
1388
+
1389
+ .assistant-history-item.active {
1390
+ background-color: var(--primary-light);
1391
+ color: white;
1392
+ }
1393
+
1394
  /* ================= تطبيق الاستجابة لمختلف الأجهزة ================= */
1395
  @media screen and (max-width: 992px) {
1396
  :root {
 
1405
  .header-nav {
1406
  margin-top: var(--spacing-md);
1407
  }
1408
+
1409
+ .assistant-container {
1410
+ flex-direction: column;
1411
+ }
1412
+
1413
+ .assistant-sidebar {
1414
+ width: 100%;
1415
+ margin-bottom: var(--spacing-md);
1416
+ }
1417
+
1418
+ .project-card-stats {
1419
+ flex-direction: column;
1420
+ gap: var(--spacing-sm);
1421
+ }
1422
  }
1423
 
1424
  @media screen and (max-width: 768px) {
 
1435
  flex-direction: column;
1436
  align-items: flex-start;
1437
  }
1438
+
1439
+ .calculation-header {
1440
+ flex-direction: column;
1441
+ align-items: flex-start;
1442
+ }
1443
+
1444
+ .calculation-controls {
1445
+ margin-top: var(--spacing-sm);
1446
+ }
1447
+
1448
+ .timeline-item {
1449
+ flex-direction: column;
1450
+ }
1451
+
1452
+ .timeline-icon {
1453
+ margin-bottom: var(--spacing-sm);
1454
+ margin-left: 0;
1455
+ }
1456
+
1457
+ .timeline-line {
1458
+ right: 20px;
1459
+ }
1460
  }
1461
 
1462
  @media screen and (max-width: 576px) {
 
1468
  .detail-actions {
1469
  margin-top: var(--spacing-md);
1470
  }
1471
+
1472
+ .ai-message-content,
1473
+ .user-message-content {
1474
+ max-width: 100%;
1475
+ }
1476
  }
utils/css/rtl.css CHANGED
@@ -1,25 +1,59 @@
1
  /*
2
- * ملف CSS للدعم العربي وتنسيق RTL
3
- * RTL support and Arabic language CSS file
 
4
  */
5
 
6
- /* تعديل الاتجاه للعناصر */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  body, .main-container, .stApp, .stMarkdown, h1, h2, h3, h4, h5, h6, p, div,
8
  input, textarea, select, button, th, td, li, span, a, label {
9
- direction: rtl;
10
- text-align: right;
 
 
 
 
 
 
 
11
  }
12
 
13
  /* تنسيقات Streamlit */
14
  .stTextInput div, .stTextArea div, .stSelectbox div, .stMultiSelect div,
15
- .stNumberInput div, .stDateInput div, .stSlider div {
16
- direction: rtl;
17
- text-align: right;
18
  }
19
 
20
- .stSidebar div {
21
- direction: rtl;
22
- text-align: right;
 
 
 
 
 
 
23
  }
24
 
25
  /* تعديل الشريط الجانبي لدعم RTL */
@@ -31,6 +65,13 @@ div[data-testid="stSidebar"] {
31
  right: 0 !important;
32
  border-left: 1px solid #e6e6e6 !important;
33
  border-right: none !important;
 
 
 
 
 
 
 
34
  }
35
 
36
  /* تغيير موضع الشريط الجانبي إلى اليمين */
@@ -38,6 +79,13 @@ div[data-testid="stSidebar"] {
38
  flex-direction: row-reverse !important;
39
  }
40
 
 
 
 
 
 
 
 
41
  /* تنسيقات إضافية لمكتبة streamlit_option_menu */
42
  .nav-link-horizontal, .nav-link {
43
  text-align: right !important;
@@ -48,6 +96,108 @@ div[data-testid="stSidebar"] {
48
  direction: rtl !important;
49
  }
50
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  .stOptionMenu ul {
52
  direction: rtl !important;
53
  padding-right: 0 !important;
@@ -358,6 +508,137 @@ form {
358
  direction: rtl;
359
  }
360
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
361
  /* تعديل الاستيراد */
362
  @media (max-width: 768px) {
363
  /* تعديلات للأجهزة الصغيرة */
@@ -365,4 +646,308 @@ form {
365
  padding-right: 0.5rem;
366
  padding-left: 0.5rem;
367
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
368
  }
 
1
  /*
2
+ * ملف CSS للدعم العربي وتنسيق RTL - مُحسن
3
+ * Enhanced RTL support and Arabic language CSS file
4
+ * WAHBi AI - تحليل العقود والمناقصات
5
  */
6
 
7
+ /* ملف الخطوط العربية */
8
+ @import url('https://fonts.googleapis.com/css2?family=Almarai:wght@300;400;700;800&display=swap');
9
+ @import url('https://fonts.googleapis.com/css2?family=Tajawal:wght@300;400;500;700;800;900&display=swap');
10
+ @import url('https://fonts.googleapis.com/css2?family=Cairo:wght@300;400;500;600;700;800;900;1000&display=swap');
11
+
12
+ :root {
13
+ --font-family-primary: 'Almarai', 'Tajawal', sans-serif;
14
+ --font-family-secondary: 'Tajawal', 'Cairo', sans-serif;
15
+ --font-family-heading: 'Cairo', 'Almarai', sans-serif;
16
+
17
+ --primary-color: #0B6E4F;
18
+ --primary-light: rgba(11, 110, 79, 0.1);
19
+ --primary-gradient: linear-gradient(135deg, #0B6E4F 0%, #08875D 100%);
20
+ --secondary-color: #08603a;
21
+ --accent-color: #FFB100;
22
+ --accent-light: rgba(255, 177, 0, 0.1);
23
+ --tertiary-color: #5754FF;
24
+ --quaternary-color: #f43f5e;
25
+ }
26
+
27
+ /* تطبيق الخطوط العربية وتعديل الاتجاه لجميع العناصر */
28
  body, .main-container, .stApp, .stMarkdown, h1, h2, h3, h4, h5, h6, p, div,
29
  input, textarea, select, button, th, td, li, span, a, label {
30
+ font-family: var(--font-family-primary) !important;
31
+ direction: rtl !important;
32
+ text-align: right !important;
33
+ }
34
+
35
+ /* تنسيقات العناوين */
36
+ h1, h2, h3 {
37
+ font-family: var(--font-family-heading) !important;
38
+ font-weight: 700 !important;
39
  }
40
 
41
  /* تنسيقات Streamlit */
42
  .stTextInput div, .stTextArea div, .stSelectbox div, .stMultiSelect div,
43
+ .stNumberInput div, .stDateInput div, .stSlider div, .stFileUploader div {
44
+ direction: rtl !important;
45
+ text-align: right !important;
46
  }
47
 
48
+ /* تنسيقات الأزرار */
49
+ button, div[data-testid="stButton"] {
50
+ direction: rtl !important;
51
+ }
52
+
53
+ /* تنسيقات القوائم المنسدلة */
54
+ select, option, .stSelectbox div, div[data-baseweb="select"] {
55
+ text-align: right !important;
56
+ direction: rtl !important;
57
  }
58
 
59
  /* تعديل الشريط الجانبي لدعم RTL */
 
65
  right: 0 !important;
66
  border-left: 1px solid #e6e6e6 !important;
67
  border-right: none !important;
68
+ padding-left: 1rem !important;
69
+ padding-right: 1rem !important;
70
+ }
71
+
72
+ .stSidebar div {
73
+ direction: rtl !important;
74
+ text-align: right !important;
75
  }
76
 
77
  /* تغيير موضع الشريط الجانبي إلى اليمين */
 
79
  flex-direction: row-reverse !important;
80
  }
81
 
82
+ /* تعديل مربعات الإدخال النصي */
83
+ input, textarea, .stTextInput input, .stTextArea textarea {
84
+ text-align: right !important;
85
+ direction: rtl !important;
86
+ padding-right: 10px !important;
87
+ }
88
+
89
  /* تنسيقات إضافية لمكتبة streamlit_option_menu */
90
  .nav-link-horizontal, .nav-link {
91
  text-align: right !important;
 
96
  direction: rtl !important;
97
  }
98
 
99
+ /* قائمة الخيارات */
100
+ .stOptionMenu li {
101
+ text-align: right !important;
102
+ direction: rtl !important;
103
+ }
104
+
105
+ /* دعم أيقونات Font Awesome بتنسيق RTL */
106
+ .fas, .fa, .far, .fal, .fab {
107
+ margin-left: 5px !important;
108
+ margin-right: 0 !important;
109
+ }
110
+
111
+ /* تعديل الجداول لدعم RTL */
112
+ .dataframe, table, div[data-testid="stTable"] {
113
+ direction: rtl !important;
114
+ text-align: right !important;
115
+ }
116
+
117
+ th, td {
118
+ text-align: right !important;
119
+ }
120
+
121
+ /* تعديلات لمخططات Plotly بدعم RTL */
122
+ .js-plotly-plot .plotly {
123
+ direction: rtl !important;
124
+ }
125
+
126
+ /* تعديل رسوم Matplotlib */
127
+ .stImage img, div[data-testid="stImage"] {
128
+ direction: rtl !important;
129
+ }
130
+
131
+ /* تعديل الإشعارات ورسائل الخطأ */
132
+ .stAlert, .stWarning, .stError, .stInfo, .stSuccess {
133
+ direction: rtl !important;
134
+ text-align: right !important;
135
+ border-right: 5px solid var(--primary-color) !important;
136
+ border-left: none !important;
137
+ padding-right: 15px !important;
138
+ }
139
+
140
+ /* تعديل مسافات المحتوى الرئيسي مع الشريط الجانبي */
141
+ .main .block-container {
142
+ padding-right: 2rem !important;
143
+ padding-left: 1rem !important;
144
+ max-width: 1200px !important;
145
+ }
146
+
147
+ /* تعديل أقسام الصفحة */
148
+ section[data-testid="stSidebar"] {
149
+ background: white !important;
150
+ border-left: 1px solid #f0f0f0 !important;
151
+ border-right: none !important;
152
+ }
153
+
154
+ /* تطبيق لون الخلفية الأساسي */
155
+ .stApp {
156
+ background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%) !important;
157
+ }
158
+
159
+ /* تعديلات التصميم المتجاوب للأجهزة المحمولة */
160
+ @media (max-width: 768px) {
161
+ .main .block-container {
162
+ padding-right: 1rem !important;
163
+ padding-left: 1rem !important;
164
+ }
165
+
166
+ h1 {
167
+ font-size: 1.8rem !important;
168
+ }
169
+
170
+ h2 {
171
+ font-size: 1.4rem !important;
172
+ }
173
+ }
174
+
175
+ /* تعديلات خاصة بالعناصر الفردية */
176
+ /* قائمة الخيارات الموسعة */
177
+ details, summary {
178
+ direction: rtl !important;
179
+ text-align: right !important;
180
+ }
181
+
182
+ /* تعديل الخيارات المتعددة وأزرار الاختيار */
183
+ div[role="radiogroup"], div[data-testid="stRadio"], div[data-testid="stCheckbox"] {
184
+ direction: rtl !important;
185
+ text-align: right !important;
186
+ }
187
+
188
+ /* تعديل شريط التمرير والنطاق */
189
+ div[data-testid="stSlider"] {
190
+ direction: rtl !important;
191
+ }
192
+
193
+ /* معالجة خاصة لعناصر الإشعارات الذكية */
194
+ .notification-card {
195
+ direction: rtl !important;
196
+ text-align: right !important;
197
+ border-right: 4px solid var(--primary-color) !important;
198
+ border-left: none !important;
199
+ }
200
+
201
  .stOptionMenu ul {
202
  direction: rtl !important;
203
  padding-right: 0 !important;
 
508
  direction: rtl;
509
  }
510
 
511
+ /* تعديلات خاصة بالمكونات المتقدمة */
512
+
513
+ /* بطاقات عرض عمليات الحساب والتحليل */
514
+ .calculation-card {
515
+ direction: rtl;
516
+ text-align: right;
517
+ border-left: none !important;
518
+ border-right: var(--border-width-lg) solid var(--primary-color) !important;
519
+ }
520
+
521
+ .calculation-header {
522
+ flex-direction: row-reverse;
523
+ }
524
+
525
+ .calculation-controls {
526
+ flex-direction: row-reverse;
527
+ }
528
+
529
+ .calculation-formula {
530
+ direction: ltr;
531
+ text-align: left;
532
+ }
533
+
534
+ /* بطاقات الذكاء الاصطناعي والتحليل الذكي */
535
+ .ai-insight-card {
536
+ direction: rtl;
537
+ text-align: right;
538
+ border-left: none !important;
539
+ border-right: var(--border-width-lg) solid var(--tertiary-color) !important;
540
+ }
541
+
542
+ .ai-insight-header {
543
+ flex-direction: row-reverse;
544
+ }
545
+
546
+ .ai-insight-icon {
547
+ margin-right: var(--spacing-md);
548
+ margin-left: 0;
549
+ }
550
+
551
+ .ai-insight-content {
552
+ border-left: none;
553
+ border-right: 3px solid var(--tertiary-color);
554
+ }
555
+
556
+ .ai-insight-tag {
557
+ margin-right: var(--spacing-sm);
558
+ margin-left: 0;
559
+ }
560
+
561
+ /* محادثة الذكاء الاصطناعي */
562
+ .ai-chat-container {
563
+ direction: rtl;
564
+ }
565
+
566
+ .ai-chat-messages {
567
+ direction: rtl;
568
+ }
569
+
570
+ .ai-message {
571
+ flex-direction: row-reverse;
572
+ }
573
+
574
+ .ai-message-avatar, .user-message-avatar {
575
+ margin-right: var(--spacing-md);
576
+ margin-left: 0;
577
+ }
578
+
579
+ .ai-message-content {
580
+ border-top-left-radius: 0;
581
+ border-top-right-radius: var(--border-radius);
582
+ }
583
+
584
+ .user-message-content {
585
+ border-top-left-radius: 0;
586
+ border-top-right-radius: var(--border-radius);
587
+ }
588
+
589
+ .ai-chat-footer {
590
+ flex-direction: row-reverse;
591
+ }
592
+
593
+ .ai-chat-input {
594
+ margin-right: var(--spacing-sm);
595
+ margin-left: 0;
596
+ }
597
+
598
+ /* بطاقات المشاريع المحسنة */
599
+ .project-card-enhanced {
600
+ direction: rtl;
601
+ text-align: right;
602
+ }
603
+
604
+ .project-card-stats {
605
+ flex-direction: row-reverse;
606
+ }
607
+
608
+ .project-tag {
609
+ margin-right: var(--spacing-sm);
610
+ margin-left: 0;
611
+ }
612
+
613
+ /* تصميم المخططات الزمنية */
614
+ .timeline-container {
615
+ direction: rtl;
616
+ }
617
+
618
+ .timeline-line {
619
+ right: auto;
620
+ left: 50px;
621
+ }
622
+
623
+ .timeline-item {
624
+ flex-direction: row-reverse;
625
+ }
626
+
627
+ .timeline-icon {
628
+ margin-right: var(--spacing-lg);
629
+ margin-left: 0;
630
+ }
631
+
632
+ /* واجهة المساعد الذكي */
633
+ .assistant-container {
634
+ flex-direction: row-reverse;
635
+ }
636
+
637
+ .assistant-history-item {
638
+ direction: rtl;
639
+ text-align: right;
640
+ }
641
+
642
  /* تعديل الاستيراد */
643
  @media (max-width: 768px) {
644
  /* تعديلات للأجهزة الصغيرة */
 
646
  padding-right: 0.5rem;
647
  padding-left: 0.5rem;
648
  }
649
+
650
+ .timeline-icon {
651
+ margin-right: 0;
652
+ margin-bottom: var(--spacing-sm);
653
+ }
654
+
655
+ .timeline-line {
656
+ left: 20px;
657
+ right: auto;
658
+ }
659
+ }
660
+
661
+ /* جداول تحليل المناقصات والعقود */
662
+ .tender-table {
663
+ width: 100%;
664
+ direction: rtl;
665
+ border-collapse: separate;
666
+ border-spacing: 0;
667
+ margin-bottom: 2rem;
668
+ }
669
+
670
+ .tender-table th {
671
+ background-color: var(--primary-color);
672
+ color: white;
673
+ text-align: right;
674
+ padding: 0.8rem 1rem;
675
+ font-weight: 700;
676
+ position: sticky;
677
+ top: 0;
678
+ z-index: 10;
679
+ }
680
+
681
+ .tender-table tr:nth-child(even) {
682
+ background-color: rgba(11, 110, 79, 0.05);
683
+ }
684
+
685
+ .tender-table td {
686
+ padding: 0.8rem 1rem;
687
+ text-align: right;
688
+ border-bottom: 1px solid rgba(0, 0, 0, 0.05);
689
+ }
690
+
691
+ .tender-table tr:hover {
692
+ background-color: rgba(11, 110, 79, 0.1);
693
+ }
694
+
695
+ /* تصميم ��ناصر تحليل البنود */
696
+ .item-analysis-container {
697
+ direction: rtl;
698
+ text-align: right;
699
+ }
700
+
701
+ .item-analysis-card {
702
+ background-color: white;
703
+ border-radius: 8px;
704
+ border-right: 4px solid var(--primary-color);
705
+ border-left: none;
706
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
707
+ padding: 1.5rem;
708
+ margin-bottom: 1.5rem;
709
+ transition: transform 0.3s ease;
710
+ }
711
+
712
+ .item-analysis-card:hover {
713
+ transform: translateY(-5px);
714
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1);
715
+ }
716
+
717
+ .item-analysis-header {
718
+ display: flex;
719
+ flex-direction: row-reverse;
720
+ justify-content: space-between;
721
+ margin-bottom: 1rem;
722
+ padding-bottom: 0.8rem;
723
+ border-bottom: 1px solid rgba(0, 0, 0, 0.1);
724
+ }
725
+
726
+ .item-analysis-title {
727
+ font-size: 1.2rem;
728
+ font-weight: 700;
729
+ color: var(--primary-color);
730
+ }
731
+
732
+ .item-analysis-badge {
733
+ font-size: 0.8rem;
734
+ font-weight: 500;
735
+ padding: 0.3rem 0.8rem;
736
+ border-radius: 20px;
737
+ }
738
+
739
+ .item-analysis-badge-high {
740
+ background-color: rgba(239, 68, 68, 0.1);
741
+ color: #DC2626;
742
+ }
743
+
744
+ .item-analysis-badge-medium {
745
+ background-color: rgba(245, 158, 11, 0.1);
746
+ color: #D97706;
747
+ }
748
+
749
+ .item-analysis-badge-low {
750
+ background-color: rgba(16, 185, 129, 0.1);
751
+ color: #059669;
752
+ }
753
+
754
+ .item-details {
755
+ display: flex;
756
+ flex-direction: column;
757
+ gap: 0.8rem;
758
+ }
759
+
760
+ .item-detail-row {
761
+ display: flex;
762
+ flex-direction: row-reverse;
763
+ justify-content: space-between;
764
+ }
765
+
766
+ .item-detail-label {
767
+ font-weight: 600;
768
+ font-size: 0.9rem;
769
+ color: #4B5563;
770
+ }
771
+
772
+ .item-detail-value {
773
+ font-weight: 400;
774
+ font-size: 0.9rem;
775
+ }
776
+
777
+ /* تصميم مقارنة الأسعار */
778
+ .price-comparison-chart {
779
+ direction: rtl;
780
+ text-align: right;
781
+ background-color: white;
782
+ border-radius: 8px;
783
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
784
+ padding: 1.5rem;
785
+ margin-bottom: 2rem;
786
+ }
787
+
788
+ .price-comparison-title {
789
+ font-size: 1.2rem;
790
+ font-weight: 700;
791
+ color: var(--primary-color);
792
+ margin-bottom: 1rem;
793
+ }
794
+
795
+ .price-legend {
796
+ display: flex;
797
+ flex-direction: row-reverse;
798
+ gap: 1.5rem;
799
+ margin-top: 1rem;
800
+ }
801
+
802
+ .price-legend-item {
803
+ display: flex;
804
+ flex-direction: row-reverse;
805
+ align-items: center;
806
+ gap: 0.5rem;
807
+ }
808
+
809
+ .price-legend-color {
810
+ width: 12px;
811
+ height: 12px;
812
+ border-radius: 2px;
813
+ }
814
+
815
+ .price-legend-label {
816
+ font-size: 0.8rem;
817
+ color: #4B5563;
818
+ }
819
+
820
+ /* تصميم تحليل المخاطر */
821
+ .risk-analysis-section {
822
+ direction: rtl;
823
+ text-align: right;
824
+ }
825
+
826
+ .risk-category {
827
+ margin-bottom: 1.5rem;
828
+ }
829
+
830
+ .risk-category-header {
831
+ background-color: white;
832
+ padding: 1rem 1.5rem;
833
+ border-radius: 8px;
834
+ display: flex;
835
+ flex-direction: row-reverse;
836
+ justify-content: space-between;
837
+ align-items: center;
838
+ margin-bottom: 1rem;
839
+ cursor: pointer;
840
+ }
841
+
842
+ .risk-category-icon {
843
+ width: 24px;
844
+ height: 24px;
845
+ border-radius: 50%;
846
+ display: flex;
847
+ justify-content: center;
848
+ align-items: center;
849
+ margin-left: 0.8rem;
850
+ margin-right: 0;
851
+ color: white;
852
+ }
853
+
854
+ .risk-category-title {
855
+ font-weight: 700;
856
+ font-size: 1rem;
857
+ }
858
+
859
+ .risk-items {
860
+ background-color: white;
861
+ border-radius: 8px;
862
+ padding: 1rem;
863
+ margin-right: 2rem;
864
+ margin-left: 0;
865
+ }
866
+
867
+ .risk-item {
868
+ padding: 1rem;
869
+ border-right: 3px solid;
870
+ border-left: none;
871
+ margin-bottom: 1rem;
872
+ border-radius: 0 4px 4px 0;
873
+ }
874
+
875
+ .risk-item-high {
876
+ border-right-color: #DC2626;
877
+ background-color: rgba(239, 68, 68, 0.05);
878
+ }
879
+
880
+ .risk-item-medium {
881
+ border-right-color: #D97706;
882
+ background-color: rgba(245, 158, 11, 0.05);
883
+ }
884
+
885
+ .risk-item-low {
886
+ border-right-color: #059669;
887
+ background-color: rgba(16, 185, 129, 0.05);
888
+ }
889
+
890
+ .risk-item-title {
891
+ font-weight: 600;
892
+ font-size: 0.95rem;
893
+ margin-bottom: 0.5rem;
894
+ }
895
+
896
+ .risk-item-description {
897
+ font-size: 0.85rem;
898
+ color: #4B5563;
899
+ }
900
+
901
+ /* تصميم عناصر التقارير */
902
+ .report-container {
903
+ direction: rtl;
904
+ text-align: right;
905
+ }
906
+
907
+ .report-header {
908
+ background-color: white;
909
+ border-radius: 8px;
910
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
911
+ padding: 2rem;
912
+ margin-bottom: 2rem;
913
+ text-align: center;
914
+ }
915
+
916
+ .report-title {
917
+ font-size: 1.5rem;
918
+ font-weight: 800;
919
+ color: var(--primary-color);
920
+ margin-bottom: 0.5rem;
921
+ }
922
+
923
+ .report-subtitle {
924
+ font-size: 1rem;
925
+ color: #6B7280;
926
+ margin-bottom: 1.5rem;
927
+ }
928
+
929
+ .report-metadata {
930
+ display: flex;
931
+ flex-direction: row-reverse;
932
+ justify-content: center;
933
+ gap: 3rem;
934
+ margin-top: 1.5rem;
935
+ }
936
+
937
+ .report-metadata-item {
938
+ display: flex;
939
+ flex-direction: column;
940
+ align-items: center;
941
+ }
942
+
943
+ .report-metadata-label {
944
+ font-size: 0.8rem;
945
+ color: #9CA3AF;
946
+ margin-bottom: 0.3rem;
947
+ }
948
+
949
+ .report-metadata-value {
950
+ font-weight: 700;
951
+ font-size: 1rem;
952
+ color: #1F2937;
953
  }