|
"""
|
|
وحدة الإشعارات الذكية - نظام تحليل المناقصات
|
|
"""
|
|
|
|
import streamlit as st
|
|
import pandas as pd
|
|
import datetime
|
|
import json
|
|
import os
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
|
|
sys.path.append(str(Path(__file__).parent.parent))
|
|
|
|
|
|
from styling.enhanced_ui import UIEnhancer
|
|
|
|
class NotificationsApp:
|
|
"""تطبيق الإشعارات الذكية"""
|
|
|
|
def __init__(self):
|
|
"""تهيئة تطبيق الإشعارات الذكية"""
|
|
self.ui = UIEnhancer(page_title="الإشعارات الذكية - نظام تحليل المناقصات", page_icon="🔔")
|
|
|
|
|
|
if 'theme' not in st.session_state:
|
|
st.session_state.theme = 'light'
|
|
|
|
self.ui.apply_theme_colors()
|
|
|
|
|
|
self.notifications_data = [
|
|
{
|
|
"id": "N001",
|
|
"title": "موعد تسليم مناقصة",
|
|
"message": "موعد تسليم مناقصة T-2025-001 (إنشاء مبنى إداري) بعد 5 أيام",
|
|
"type": "deadline",
|
|
"priority": "high",
|
|
"related_entity": "T-2025-001",
|
|
"created_at": "2025-03-25T10:30:00",
|
|
"is_read": False
|
|
},
|
|
{
|
|
"id": "N002",
|
|
"title": "ترسية مناقصة",
|
|
"message": "تم ترسية مناقصة T-2025-003 (توريد معدات) بنجاح",
|
|
"type": "award",
|
|
"priority": "medium",
|
|
"related_entity": "T-2025-003",
|
|
"created_at": "2025-03-28T14:15:00",
|
|
"is_read": True
|
|
},
|
|
{
|
|
"id": "N003",
|
|
"title": "تحديث مستندات",
|
|
"message": "تم تحديث مستندات مناقصة T-2025-002 (صيانة طرق)",
|
|
"type": "document",
|
|
"priority": "medium",
|
|
"related_entity": "T-2025-002",
|
|
"created_at": "2025-03-29T09:45:00",
|
|
"is_read": False
|
|
},
|
|
{
|
|
"id": "N004",
|
|
"title": "تغيير في المواصفات",
|
|
"message": "تم تغيير المواصفات الفنية لمناقصة T-2025-001 (إنشاء مبنى إداري)",
|
|
"type": "change",
|
|
"priority": "high",
|
|
"related_entity": "T-2025-001",
|
|
"created_at": "2025-03-27T11:20:00",
|
|
"is_read": False
|
|
},
|
|
{
|
|
"id": "N005",
|
|
"title": "تأخير في المشروع",
|
|
"message": "تأخير في تنفيذ مشروع P002 (تطوير طريق الملك فهد - جدة)",
|
|
"type": "delay",
|
|
"priority": "high",
|
|
"related_entity": "P002",
|
|
"created_at": "2025-03-26T16:10:00",
|
|
"is_read": True
|
|
},
|
|
{
|
|
"id": "N006",
|
|
"title": "اكتمال مرحلة",
|
|
"message": "اكتمال مرحلة الأساسات في مشروع P001 (إنشاء مبنى إداري - الرياض)",
|
|
"type": "milestone",
|
|
"priority": "low",
|
|
"related_entity": "P001",
|
|
"created_at": "2025-03-24T13:30:00",
|
|
"is_read": True
|
|
},
|
|
{
|
|
"id": "N007",
|
|
"title": "طلب معلومات إضافية",
|
|
"message": "طلب معلومات إضافية لمناقصة T-2025-004 (تجهيز مختبرات)",
|
|
"type": "request",
|
|
"priority": "medium",
|
|
"related_entity": "T-2025-004",
|
|
"created_at": "2025-03-30T08:15:00",
|
|
"is_read": False
|
|
},
|
|
{
|
|
"id": "N008",
|
|
"title": "تحديث أسعار المواد",
|
|
"message": "تم تحديث أسعار مواد البناء في قاعدة البيانات",
|
|
"type": "update",
|
|
"priority": "low",
|
|
"related_entity": "DB-MATERIALS",
|
|
"created_at": "2025-03-29T15:40:00",
|
|
"is_read": False
|
|
},
|
|
{
|
|
"id": "N009",
|
|
"title": "اجتماع فريق العمل",
|
|
"message": "اجتماع فريق العمل لمناقشة مناقصة T-2025-001 غداً الساعة 10:00 صباحاً",
|
|
"type": "meeting",
|
|
"priority": "medium",
|
|
"related_entity": "T-2025-001",
|
|
"created_at": "2025-03-28T16:20:00",
|
|
"is_read": True
|
|
},
|
|
{
|
|
"id": "N010",
|
|
"title": "تغيير في الميزانية",
|
|
"message": "تم تغيير الميزانية المخصصة لمشروع P004 (بناء مدرسة - أبها)",
|
|
"type": "budget",
|
|
"priority": "high",
|
|
"related_entity": "P004",
|
|
"created_at": "2025-03-25T14:50:00",
|
|
"is_read": False
|
|
}
|
|
]
|
|
|
|
|
|
self.notification_settings = {
|
|
"deadline": True,
|
|
"award": True,
|
|
"document": True,
|
|
"change": True,
|
|
"delay": True,
|
|
"milestone": True,
|
|
"request": True,
|
|
"update": True,
|
|
"meeting": True,
|
|
"budget": True,
|
|
"email_notifications": True,
|
|
"sms_notifications": False,
|
|
"push_notifications": True,
|
|
"notification_frequency": "realtime"
|
|
}
|
|
|
|
def run(self):
|
|
"""تشغيل تطبيق الإشعارات الذكية"""
|
|
|
|
col1, col2, col3 = st.columns([1, 8, 1])
|
|
with col3:
|
|
if st.button("🌓 تبديل السمة"):
|
|
|
|
if st.session_state.theme == "light":
|
|
st.session_state.theme = "dark"
|
|
else:
|
|
st.session_state.theme = "light"
|
|
|
|
|
|
self.ui.theme_mode = st.session_state.theme
|
|
self.ui.apply_theme_colors()
|
|
st.rerun()
|
|
|
|
|
|
self.ui.create_header("الإشعارات الذكية", "إدارة ومتابعة الإشعارات والتنبيهات")
|
|
|
|
|
|
tabs = st.tabs(["الإشعارات الحالية", "إعدادات الإشعارات", "إنشاء إشعار", "سجل الإشعارات"])
|
|
|
|
|
|
with tabs[0]:
|
|
self.show_current_notifications()
|
|
|
|
|
|
with tabs[1]:
|
|
self.show_notification_settings()
|
|
|
|
|
|
with tabs[2]:
|
|
self.create_notification()
|
|
|
|
|
|
with tabs[3]:
|
|
self.show_notification_history()
|
|
|
|
def show_current_notifications(self):
|
|
"""عرض الإشعارات الحالية"""
|
|
st.markdown("### الإشعارات الحالية")
|
|
|
|
|
|
col1, col2, col3 = st.columns(3)
|
|
|
|
with col1:
|
|
type_filter = st.multiselect(
|
|
"نوع الإشعار",
|
|
options=["الكل", "موعد نهائي", "ترسية", "مستند", "تغيير", "تأخير", "مرحلة", "طلب", "تحديث", "اجتماع", "ميزانية"],
|
|
default=["الكل"]
|
|
)
|
|
|
|
with col2:
|
|
priority_filter = st.multiselect(
|
|
"الأولوية",
|
|
options=["الكل", "عالية", "متوسطة", "منخفضة"],
|
|
default=["الكل"]
|
|
)
|
|
|
|
with col3:
|
|
read_filter = st.radio(
|
|
"الحالة",
|
|
options=["الكل", "غير مقروءة", "مقروءة"],
|
|
horizontal=True
|
|
)
|
|
|
|
|
|
filtered_notifications = self.notifications_data
|
|
|
|
|
|
type_mapping = {
|
|
"موعد نهائي": "deadline",
|
|
"ترسية": "award",
|
|
"مستند": "document",
|
|
"تغيير": "change",
|
|
"تأخير": "delay",
|
|
"مرحلة": "milestone",
|
|
"طلب": "request",
|
|
"تحديث": "update",
|
|
"اجتماع": "meeting",
|
|
"ميزانية": "budget"
|
|
}
|
|
|
|
|
|
priority_mapping = {
|
|
"عالية": "high",
|
|
"متوسطة": "medium",
|
|
"منخفضة": "low"
|
|
}
|
|
|
|
if "الكل" not in type_filter and type_filter:
|
|
filtered_types = [type_mapping[t] for t in type_filter if t in type_mapping]
|
|
filtered_notifications = [n for n in filtered_notifications if n["type"] in filtered_types]
|
|
|
|
if "الكل" not in priority_filter and priority_filter:
|
|
filtered_priorities = [priority_mapping[p] for p in priority_filter if p in priority_mapping]
|
|
filtered_notifications = [n for n in filtered_notifications if n["priority"] in filtered_priorities]
|
|
|
|
if read_filter == "غير مقروءة":
|
|
filtered_notifications = [n for n in filtered_notifications if not n["is_read"]]
|
|
elif read_filter == "مقروءة":
|
|
filtered_notifications = [n for n in filtered_notifications if n["is_read"]]
|
|
|
|
|
|
unread_count = len([n for n in filtered_notifications if not n["is_read"]])
|
|
|
|
st.markdown(f"**عدد الإشعارات غير المقروءة:** {unread_count}")
|
|
|
|
|
|
col1, col2 = st.columns([1, 1])
|
|
with col1:
|
|
if st.button("تحديث الإشعارات", use_container_width=True):
|
|
st.success("تم تحديث الإشعارات بنجاح")
|
|
|
|
with col2:
|
|
if st.button("تعليم الكل كمقروء", use_container_width=True):
|
|
st.success("تم تعليم جميع الإشعارات كمقروءة")
|
|
|
|
|
|
if not filtered_notifications:
|
|
st.info("لا توجد إشعارات تطابق الفلاتر المحددة")
|
|
else:
|
|
for notification in filtered_notifications:
|
|
self.display_notification(notification)
|
|
|
|
def display_notification(self, notification):
|
|
"""عرض إشعار واحد"""
|
|
|
|
if notification["priority"] == "high":
|
|
color = self.ui.COLORS['danger']
|
|
priority_text = "عالية"
|
|
elif notification["priority"] == "medium":
|
|
color = self.ui.COLORS['warning']
|
|
priority_text = "متوسطة"
|
|
else:
|
|
color = self.ui.COLORS['secondary']
|
|
priority_text = "منخفضة"
|
|
|
|
|
|
type_mapping = {
|
|
"deadline": "موعد نهائي",
|
|
"award": "ترسية",
|
|
"document": "مستند",
|
|
"change": "تغيير",
|
|
"delay": "تأخير",
|
|
"milestone": "مرحلة",
|
|
"request": "طلب",
|
|
"update": "تحديث",
|
|
"meeting": "اجتماع",
|
|
"budget": "ميزانية"
|
|
}
|
|
|
|
notification_type = type_mapping.get(notification["type"], notification["type"])
|
|
|
|
|
|
created_at = datetime.datetime.fromisoformat(notification["created_at"])
|
|
formatted_date = created_at.strftime("%Y-%m-%d %H:%M")
|
|
|
|
|
|
icon_mapping = {
|
|
"deadline": "⏰",
|
|
"award": "🏆",
|
|
"document": "📄",
|
|
"change": "🔄",
|
|
"delay": "⚠️",
|
|
"milestone": "🏁",
|
|
"request": "❓",
|
|
"update": "🔄",
|
|
"meeting": "👥",
|
|
"budget": "💰"
|
|
}
|
|
|
|
icon = icon_mapping.get(notification["type"], "📌")
|
|
|
|
|
|
st.markdown(
|
|
f"""
|
|
<div style="border-left: 5px solid {color}; padding: 10px; margin-bottom: 10px; background-color: {'#f8f9fa' if st.session_state.theme == 'light' else '#2b2b2b'}; border-radius: 5px; {'opacity: 0.7;' if notification['is_read'] else ''}">
|
|
<div style="display: flex; justify-content: space-between; align-items: center;">
|
|
<div>
|
|
<h4 style="margin: 0;">{icon} {notification['title']}</h4>
|
|
<p style="margin: 5px 0;">{notification['message']}</p>
|
|
<div style="display: flex; gap: 10px; font-size: 0.8em; color: {'#6c757d' if st.session_state.theme == 'light' else '#adb5bd'};">
|
|
<span>النوع: {notification_type}</span>
|
|
<span>الأولوية: {priority_text}</span>
|
|
<span>التاريخ: {formatted_date}</span>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<button style="background: none; border: none; cursor: pointer; color: {'#6c757d' if st.session_state.theme == 'light' else '#adb5bd'};">✓</button>
|
|
<button style="background: none; border: none; cursor: pointer; color: {'#6c757d' if st.session_state.theme == 'light' else '#adb5bd'};">🗑️</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
""",
|
|
unsafe_allow_html=True
|
|
)
|
|
|
|
def show_notification_settings(self):
|
|
"""عرض إعدادات الإشعارات"""
|
|
st.markdown("### إعدادات الإشعارات")
|
|
|
|
|
|
with st.form("notification_settings_form"):
|
|
st.markdown("#### أنواع الإشعارات")
|
|
|
|
col1, col2 = st.columns(2)
|
|
|
|
with col1:
|
|
deadline = st.checkbox("المواعيد النهائية", value=self.notification_settings["deadline"])
|
|
award = st.checkbox("ترسية المناقصات", value=self.notification_settings["award"])
|
|
document = st.checkbox("تحديثات المستندات", value=self.notification_settings["document"])
|
|
change = st.checkbox("التغييرات في المواصفات", value=self.notification_settings["change"])
|
|
delay = st.checkbox("التأخيرات في المشاريع", value=self.notification_settings["delay"])
|
|
|
|
with col2:
|
|
milestone = st.checkbox("اكتمال المراحل", value=self.notification_settings["milestone"])
|
|
request = st.checkbox("طلبات المعلومات", value=self.notification_settings["request"])
|
|
update = st.checkbox("تحديثات النظام", value=self.notification_settings["update"])
|
|
meeting = st.checkbox("الاجتماعات", value=self.notification_settings["meeting"])
|
|
budget = st.checkbox("تغييرات الميزانية", value=self.notification_settings["budget"])
|
|
|
|
st.markdown("#### طرق الإشعار")
|
|
|
|
col1, col2, col3 = st.columns(3)
|
|
|
|
with col1:
|
|
email_notifications = st.checkbox("البريد الإلكتروني", value=self.notification_settings["email_notifications"])
|
|
|
|
with col2:
|
|
sms_notifications = st.checkbox("الرسائل النصية", value=self.notification_settings["sms_notifications"])
|
|
|
|
with col3:
|
|
push_notifications = st.checkbox("إشعارات الويب", value=self.notification_settings["push_notifications"])
|
|
|
|
st.markdown("#### تكرار الإشعارات")
|
|
|
|
notification_frequency = st.radio(
|
|
"تكرار الإشعارات",
|
|
options=["في الوقت الحقيقي", "مرة واحدة يومياً", "مرة واحدة أسبوعياً"],
|
|
index=0 if self.notification_settings["notification_frequency"] == "realtime" else 1 if self.notification_settings["notification_frequency"] == "daily" else 2,
|
|
horizontal=True
|
|
)
|
|
|
|
|
|
submit_button = st.form_submit_button("حفظ الإعدادات")
|
|
|
|
if submit_button:
|
|
|
|
self.notification_settings.update({
|
|
"deadline": deadline,
|
|
"award": award,
|
|
"document": document,
|
|
"change": change,
|
|
"delay": delay,
|
|
"milestone": milestone,
|
|
"request": request,
|
|
"update": update,
|
|
"meeting": meeting,
|
|
"budget": budget,
|
|
"email_notifications": email_notifications,
|
|
"sms_notifications": sms_notifications,
|
|
"push_notifications": push_notifications,
|
|
"notification_frequency": "realtime" if notification_frequency == "في الوقت الحقيقي" else "daily" if notification_frequency == "مرة واحدة يومياً" else "weekly"
|
|
})
|
|
|
|
st.success("تم حفظ الإعدادات بنجاح")
|
|
|
|
|
|
st.markdown("### إعدادات متقدمة")
|
|
|
|
with st.expander("إعدادات متقدمة"):
|
|
st.markdown("#### جدولة الإشعارات")
|
|
|
|
col1, col2 = st.columns(2)
|
|
|
|
with col1:
|
|
st.time_input("وقت الإشعارات اليومية", datetime.time(9, 0))
|
|
|
|
with col2:
|
|
st.selectbox(
|
|
"يوم الإشعارات الأسبوعية",
|
|
options=["الأحد", "الاثنين", "الثلاثاء", "الأربعاء", "الخميس", "الجمعة", "السبت"],
|
|
index=0
|
|
)
|
|
|
|
st.markdown("#### فلترة الإشعارات")
|
|
|
|
min_priority = st.select_slider(
|
|
"الحد الأدنى للأولوية",
|
|
options=["منخفضة", "متوسطة", "عالية"],
|
|
value="منخفضة"
|
|
)
|
|
|
|
st.markdown("#### حفظ الإشعارات")
|
|
|
|
retention_period = st.slider(
|
|
"فترة الاحتفاظ بالإشعارات (بالأيام)",
|
|
min_value=7,
|
|
max_value=365,
|
|
value=90,
|
|
step=1
|
|
)
|
|
|
|
if st.button("حفظ الإعدادات المتقدمة"):
|
|
st.success("تم حفظ الإعدادات المتقدمة بنجاح")
|
|
|
|
def create_notification(self):
|
|
"""إنشاء إشعار جديد"""
|
|
st.markdown("### إنشاء إشعار جديد")
|
|
|
|
|
|
with st.form("new_notification_form"):
|
|
title = st.text_input("عنوان الإشعار")
|
|
message = st.text_area("نص الإشعار")
|
|
|
|
col1, col2 = st.columns(2)
|
|
|
|
with col1:
|
|
notification_type = st.selectbox(
|
|
"نوع الإشعار",
|
|
options=["موعد نهائي", "ترسية", "مستند", "تغيير", "تأخير", "مرحلة", "طلب", "تحديث", "اجتماع", "ميزانية"]
|
|
)
|
|
|
|
|
|
type_mapping = {
|
|
"موعد نهائي": "deadline",
|
|
"ترسية": "award",
|
|
"مستند": "document",
|
|
"تغيير": "change",
|
|
"تأخير": "delay",
|
|
"مرحلة": "milestone",
|
|
"طلب": "request",
|
|
"تحديث": "update",
|
|
"اجتماع": "meeting",
|
|
"ميزانية": "budget"
|
|
}
|
|
|
|
notification_type_en = type_mapping.get(notification_type, "deadline")
|
|
|
|
priority = st.selectbox(
|
|
"الأولوية",
|
|
options=["عالية", "متوسطة", "منخفضة"]
|
|
)
|
|
|
|
|
|
priority_mapping = {
|
|
"عالية": "high",
|
|
"متوسطة": "medium",
|
|
"منخفضة": "low"
|
|
}
|
|
|
|
priority_en = priority_mapping.get(priority, "medium")
|
|
|
|
with col2:
|
|
related_entity = st.text_input("الكيان المرتبط (مثل: رقم المناقصة، رقم المشروع)")
|
|
|
|
notification_date = st.date_input(
|
|
"تاريخ الإشعار",
|
|
value=datetime.datetime.now().date()
|
|
)
|
|
|
|
notification_time = st.time_input(
|
|
"وقت الإشعار",
|
|
value=datetime.datetime.now().time()
|
|
)
|
|
|
|
|
|
submit_button = st.form_submit_button("إنشاء الإشعار")
|
|
|
|
if submit_button and title and message:
|
|
|
|
new_id = f"N{len(self.notifications_data) + 1:03d}"
|
|
|
|
|
|
notification_datetime = datetime.datetime.combine(notification_date, notification_time)
|
|
notification_datetime_iso = notification_datetime.isoformat()
|
|
|
|
|
|
self.notifications_data.append({
|
|
"id": new_id,
|
|
"title": title,
|
|
"message": message,
|
|
"type": notification_type_en,
|
|
"priority": priority_en,
|
|
"related_entity": related_entity,
|
|
"created_at": notification_datetime_iso,
|
|
"is_read": False
|
|
})
|
|
|
|
st.success("تم إنشاء الإشعار بنجاح")
|
|
|
|
|
|
st.markdown("### الإشعار الجديد")
|
|
self.display_notification(self.notifications_data[-1])
|
|
|
|
|
|
st.markdown("### إنشاء إشعارات متعددة")
|
|
|
|
with st.expander("إنشاء إشعارات متعددة"):
|
|
st.markdown("#### تحميل ملف إشعارات")
|
|
|
|
uploaded_file = st.file_uploader("قم بتحميل ملف إشعارات (CSV, JSON)", type=["csv", "json"])
|
|
|
|
if uploaded_file is not None:
|
|
if st.button("استيراد الإشعارات"):
|
|
st.success("تم استيراد الإشعارات بنجاح")
|
|
|
|
st.markdown("#### إنشاء إشعارات من قالب")
|
|
|
|
template_type = st.selectbox(
|
|
"نوع القالب",
|
|
options=["إشعارات المواعيد النهائية", "إشعارات الاجتماعات", "إشعارات التحديثات"]
|
|
)
|
|
|
|
if st.button("إنشاء إشعارات من القالب"):
|
|
st.success("تم إنشاء الإشعارات من القالب بنجاح")
|
|
|
|
def show_notification_history(self):
|
|
"""عرض سجل الإشعارات"""
|
|
st.markdown("### سجل الإشعارات")
|
|
|
|
|
|
col1, col2 = st.columns(2)
|
|
|
|
with col1:
|
|
date_range = st.date_input(
|
|
"نطاق التاريخ",
|
|
value=(
|
|
datetime.datetime.now().date() - datetime.timedelta(days=30),
|
|
datetime.datetime.now().date()
|
|
)
|
|
)
|
|
|
|
with col2:
|
|
entity_filter = st.text_input("الكيان المرتبط")
|
|
|
|
|
|
notifications_df = pd.DataFrame(self.notifications_data)
|
|
|
|
|
|
notifications_df["created_at"] = pd.to_datetime(notifications_df["created_at"])
|
|
|
|
|
|
if len(date_range) == 2:
|
|
start_date, end_date = date_range
|
|
start_date = pd.to_datetime(start_date)
|
|
end_date = pd.to_datetime(end_date) + pd.Timedelta(days=1) - pd.Timedelta(seconds=1)
|
|
|
|
notifications_df = notifications_df[
|
|
(notifications_df["created_at"] >= start_date) &
|
|
(notifications_df["created_at"] <= end_date)
|
|
]
|
|
|
|
|
|
if entity_filter:
|
|
notifications_df = notifications_df[
|
|
notifications_df["related_entity"].str.contains(entity_filter, case=False)
|
|
]
|
|
|
|
|
|
type_mapping = {
|
|
"deadline": "موعد نهائي",
|
|
"award": "ترسية",
|
|
"document": "مستند",
|
|
"change": "تغيير",
|
|
"delay": "تأخير",
|
|
"milestone": "مرحلة",
|
|
"request": "طلب",
|
|
"update": "تحديث",
|
|
"meeting": "اجتماع",
|
|
"budget": "ميزانية"
|
|
}
|
|
|
|
notifications_df["type_ar"] = notifications_df["type"].map(type_mapping)
|
|
|
|
|
|
priority_mapping = {
|
|
"high": "عالية",
|
|
"medium": "متوسطة",
|
|
"low": "منخفضة"
|
|
}
|
|
|
|
notifications_df["priority_ar"] = notifications_df["priority"].map(priority_mapping)
|
|
|
|
|
|
notifications_df["is_read_text"] = notifications_df["is_read"].map({True: "مقروءة", False: "غير مقروءة"})
|
|
|
|
|
|
notifications_df["created_at_formatted"] = notifications_df["created_at"].dt.strftime("%Y-%m-%d %H:%M")
|
|
|
|
|
|
display_df = notifications_df[[
|
|
"id", "title", "type_ar", "priority_ar", "related_entity",
|
|
"created_at_formatted", "is_read_text"
|
|
]].rename(columns={
|
|
"id": "الرقم",
|
|
"title": "العنوان",
|
|
"type_ar": "النوع",
|
|
"priority_ar": "الأولوية",
|
|
"related_entity": "الكيان المرتبط",
|
|
"created_at_formatted": "التاريخ",
|
|
"is_read_text": "الحالة"
|
|
})
|
|
|
|
|
|
st.dataframe(display_df, use_container_width=True, hide_index=True)
|
|
|
|
|
|
st.markdown("### إحصائيات الإشعارات")
|
|
|
|
col1, col2, col3 = st.columns(3)
|
|
|
|
with col1:
|
|
total_count = len(notifications_df)
|
|
st.metric("إجمالي الإشعارات", total_count)
|
|
|
|
with col2:
|
|
read_count = len(notifications_df[notifications_df["is_read"] == True])
|
|
st.metric("الإشعارات المقروءة", read_count)
|
|
|
|
with col3:
|
|
unread_count = len(notifications_df[notifications_df["is_read"] == False])
|
|
st.metric("الإشعارات غير المقروءة", unread_count)
|
|
|
|
|
|
st.markdown("#### توزيع الإشعارات حسب النوع")
|
|
|
|
type_counts = notifications_df["type_ar"].value_counts().reset_index()
|
|
type_counts.columns = ["النوع", "العدد"]
|
|
|
|
st.bar_chart(type_counts, x="النوع", y="العدد")
|
|
|
|
|
|
st.markdown("#### توزيع الإشعارات حسب الأولوية")
|
|
|
|
priority_counts = notifications_df["priority_ar"].value_counts().reset_index()
|
|
priority_counts.columns = ["الأولوية", "العدد"]
|
|
|
|
st.bar_chart(priority_counts, x="الأولوية", y="العدد")
|
|
|
|
|
|
st.markdown("### تصدير البيانات")
|
|
|
|
col1, col2 = st.columns(2)
|
|
|
|
with col1:
|
|
if st.button("تصدير إلى CSV"):
|
|
st.success("تم تصدير البيانات إلى CSV بنجاح")
|
|
|
|
with col2:
|
|
if st.button("تصدير إلى Excel"):
|
|
st.success("تم تصدير البيانات إلى Excel بنجاح")
|
|
|