"""
تحسينات التصميم المرئي وواجهة المستخدم لنظام تحليل المناقصات
"""
import streamlit as st
import streamlit_option_menu as option_menu
from streamlit_extras.colored_header import colored_header
from streamlit_extras.switch_page_button import switch_page
import os
import sys
from pathlib import Path
# إضافة مسار المشروع للنظام
sys.path.append(str(Path(__file__).parent.parent))
class UIEnhancer:
"""فئة لتحسين واجهة المستخدم وتوحيد التصميم المرئي عبر النظام"""
# ألوان النظام
COLORS = {
'primary': '#1E5F74', # أزرق داكن للعناصر الرئيسية
'secondary': '#4BA3C3', # أزرق فاتح للعناصر الثانوية
'accent': '#F39237', # برتقالي للتأكيد والأزرار المهمة
'success': '#4CAF50', # أخضر للنجاح
'warning': '#FFC107', # أصفر للتحذيرات
'danger': '#E63946', # أحمر للأخطاء
'light': '#F5F5F5', # فاتح للخلفيات في الوضع الفاتح
'dark': '#1A1A1A', # داكن للخلفيات في الوضع الداكن
'text_light': '#FFFFFF', # نص أبيض للوضع الداكن
'text_dark': '#333333', # نص داكن للوضع الفاتح
'border': '#DDDDDD', # لون الحدود
'hover': '#2A7F9E', # لون التحويم
}
# أنماط CSS المخصصة
CUSTOM_CSS = """
"""
def __init__(self, page_title="نظام تحليل المناقصات", page_icon="📊", layout="wide"):
"""تهيئة محسن واجهة المستخدم"""
self.page_title = page_title
self.page_icon = page_icon
self.layout = layout
self.setup_page()
def setup_page(self):
"""إعداد الصفحة وتطبيق الإعدادات العامة"""
st.set_page_config(
page_title=self.page_title,
page_icon=self.page_icon,
layout=self.layout,
initial_sidebar_state="expanded"
)
# تطبيق CSS المخصص
st.markdown(self.CUSTOM_CSS, unsafe_allow_html=True)
# إعداد متغيرات الجلسة إذا لم تكن موجودة
if 'theme' not in st.session_state:
st.session_state.theme = 'light'
if 'language' not in st.session_state:
st.session_state.language = 'ar'
def create_sidebar(self, menu_items):
"""إنشاء شريط جانبي محسن مع قائمة"""
with st.sidebar:
# عرض الشعار والعنوان
st.markdown(
f"""
{self.page_title}
""",
unsafe_allow_html=True
)
# إنشاء قائمة الخيارات
selected = option_menu.option_menu(
menu_title=None,
options=[item["name"] for item in menu_items],
icons=[item["icon"] for item in menu_items],
menu_icon="cast",
default_index=0,
styles={
"container": {"padding": "0!important", "background-color": f"{self.COLORS['primary']}"},
"icon": {"color": "white", "font-size": "18px"},
"nav-link": {"color": "white", "font-size": "16px", "text-align": "right", "margin":"0px"},
"nav-link-selected": {"background-color": f"{self.COLORS['accent']}"},
}
)
# إضافة مفتاح تبديل السمة
st.markdown("
", unsafe_allow_html=True)
col1, col2 = st.columns([1, 3])
with col1:
st.write("السمة:")
with col2:
if st.toggle("الوضع الداكن", st.session_state.theme == 'dark'):
st.session_state.theme = 'dark'
else:
st.session_state.theme = 'light'
# إضافة معلومات المستخدم
st.markdown("
", unsafe_allow_html=True)
st.markdown(
f"""
مرحباً، المستخدم
""",
unsafe_allow_html=True
)
return selected
def create_header(self, title, description=None):
"""إنشاء ترويسة محسنة للصفحة"""
colored_header(
label=title,
description=description,
color_name=self.COLORS['primary']
)
def create_card(self, title, content, color=None):
"""إنشاء بطاقة محسنة"""
bg_color = color if color else self.COLORS['light'] if st.session_state.theme == 'light' else self.COLORS['dark']
text_color = self.COLORS['text_dark'] if st.session_state.theme == 'light' else self.COLORS['text_light']
st.markdown(
f"""
""",
unsafe_allow_html=True
)
def create_metric_card(self, title, value, delta=None, color=None):
"""إنشاء بطاقة مقاييس محسنة"""
bg_color = color if color else self.COLORS['primary']
delta_html = f" 0 else 'red'};'>{delta}%" if delta is not None else ""
st.markdown(
f"""
{title}
{value}
{delta_html}
""",
unsafe_allow_html=True
)
def create_notification(self, message, type_="info"):
"""إنشاء إشعار محسن"""
colors = {
"info": self.COLORS['secondary'],
"success": self.COLORS['success'],
"warning": self.COLORS['warning'],
"error": self.COLORS['danger']
}
icons = {
"info": "ℹ️",
"success": "✅",
"warning": "⚠️",
"error": "❌"
}
bg_color = colors.get(type_, colors["info"])
icon = icons.get(type_, icons["info"])
st.markdown(
f"""
""",
unsafe_allow_html=True
)
def create_button(self, label, type_="primary", on_click=None):
"""إنشاء زر محسن"""
colors = {
"primary": self.COLORS['primary'],
"secondary": self.COLORS['secondary'],
"accent": self.COLORS['accent'],
"success": self.COLORS['success'],
"warning": self.COLORS['warning'],
"danger": self.COLORS['danger']
}
bg_color = colors.get(type_, colors["primary"])
text_color = self.COLORS['text_light']
return st.button(
label,
key=f"btn_{label}_{type_}",
on_click=on_click,
use_container_width=True
)
def create_table(self, data, columns):
"""إنشاء جدول محسن"""
# تحويل البيانات إلى HTML
table_html = f"""
{"".join([f"{col} | " for col in columns])}
"""
for row in data:
table_html += ""
for col in columns:
table_html += f"{row.get(col, '')} | "
table_html += "
"
table_html += """
"""
st.markdown(table_html, unsafe_allow_html=True)
def apply_theme_colors(self):
"""تطبيق ألوان السمة الحالية"""
theme_colors = {
'light': {
'background': self.COLORS['light'],
'text': self.COLORS['text_dark'],
'border': self.COLORS['border']
},
'dark': {
'background': self.COLORS['dark'],
'text': self.COLORS['text_light'],
'border': '#444444'
}
}
current_theme = theme_colors[st.session_state.theme]
st.markdown(
f"""
""",
unsafe_allow_html=True
)
# استخدام الفئة
if __name__ == "__main__":
ui = UIEnhancer()
ui.apply_theme_colors()
# إنشاء قائمة العناصر
menu_items = [
{"name": "لوحة المعلومات", "icon": "house"},
{"name": "المناقصات والعقود", "icon": "file-text"},
{"name": "تحليل المستندات", "icon": "file-earmark-text"},
{"name": "نظام التسعير", "icon": "calculator"},
{"name": "حاسبة تكاليف البناء", "icon": "building"},
{"name": "الموارد والتكاليف", "icon": "people"},
{"name": "تحليل المخاطر", "icon": "exclamation-triangle"},
{"name": "إدارة المشاريع", "icon": "kanban"},
{"name": "الخرائط والمواقع", "icon": "geo-alt"},
{"name": "الجدول الزمني", "icon": "calendar3"},
{"name": "الإشعارات", "icon": "bell"},
{"name": "مقارنة المستندات", "icon": "files"},
{"name": "المساعد الذكي", "icon": "robot"},
{"name": "التقارير", "icon": "bar-chart"},
{"name": "الإعدادات", "icon": "gear"}
]
# إنشاء الشريط الجانبي
selected = ui.create_sidebar(menu_items)
# إنشاء ترويسة الصفحة
ui.create_header("لوحة المعلومات", "نظرة عامة على المناقصات والمشاريع")
# إنشاء صفوف للمقاييس
col1, col2, col3, col4 = st.columns(4)
with col1:
ui.create_metric_card("المناقصات النشطة", "12", delta=5)
with col2:
ui.create_metric_card("المشاريع الجارية", "8", delta=-2)
with col3:
ui.create_metric_card("المناقصات المربوحة", "65%", delta=10)
with col4:
ui.create_metric_card("قيمة المشاريع", "25M ريال", delta=15)
# إنشاء صفين للبطاقات والإشعارات
col1, col2 = st.columns([2, 1])
with col1:
ui.create_header("المناقصات الحالية", "آخر تحديث: اليوم")
# بيانات المناقصات
tenders_data = [
{"رقم المناقصة": "T-2025-001", "العنوان": "إنشاء مبنى إداري", "الحالة": "قيد الدراسة", "تاريخ التقديم": "2025-04-15"},
{"رقم المناقصة": "T-2025-002", "العنوان": "صيانة طرق", "الحالة": "تم التقديم", "تاريخ التقديم": "2025-03-20"},
{"رقم المناقصة": "T-2025-003", "العنوان": "توريد معدات", "الحالة": "فائز", "تاريخ التقديم": "2025-02-10"}
]
ui.create_table(tenders_data, ["رقم المناقصة", "العنوان", "الحالة", "تاريخ التقديم"])
with col2:
ui.create_header("الإشعارات", "آخر التنبيهات")
ui.create_notification("موعد تسليم مناقصة T-2025-001 بعد 5 أيام", "warning")
ui.create_notification("تم ترسية مناقصة T-2025-003", "success")
ui.create_notification("تم تحديث مستندات مناقصة T-2025-002", "info")
st.markdown("
", unsafe_allow_html=True)
ui.create_button("عرض جميع الإشعارات", "secondary")
# إنشاء صف للبطاقات
st.markdown("
", unsafe_allow_html=True)
ui.create_header("الإجراءات السريعة", "اختر إجراءً للبدء")
col1, col2, col3 = st.columns(3)
with col1:
ui.create_card(
"إضافة مناقصة جديدة",
"إنشاء مناقصة جديدة وإدخال البيانات الأساسية"
)
with col2:
ui.create_card(
"تحليل مستند",
"تحميل مستند مناقصة جديد للتحليل التلقائي"
)
with col3:
ui.create_card(
"إنشاء تقرير",
"إنشاء تقارير مخصصة للمناقصات والمشاريع"
)