""" تحسينات التصميم المرئي وواجهة المستخدم لنظام تحليل المناقصات """ 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"""

{title}

{content}

""", 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"""
{icon}
{message}
""", 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"" for col in columns])} """ for row in data: table_html += "" for col in columns: table_html += f"" table_html += "" table_html += """
{col}
{row.get(col, '')}
""" 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( "إنشاء تقرير", "إنشاء تقارير مخصصة للمناقصات والمشاريع" )