import streamlit as st import sqlite3 from datetime import datetime from passlib.hash import bcrypt import os import shutil from dotenv import load_dotenv # تهيئة الصفحة st.set_page_config(page_title="نظام إدارة الشكاوى", layout="centered") # تحميل متغيرات البيئة load_dotenv() ADMIN_DB_PASSWORD = os.getenv("ADMIN_DB_PASS", "Admin@1234") # كلمة مرور افتراضية إذا لم يتم تعيينها # إدارة اتصال قاعدة البيانات def get_db_connection(): conn = sqlite3.connect("complaintsBD.db", check_same_thread=False) conn.row_factory = sqlite3.Row return conn # إنشاء الجداول والتأكد من وجود جميع الأعمدة def init_db(): conn = get_db_connection() # إنشاء جدول المستخدمين إذا لم يكن موجوداً conn.execute(""" CREATE TABLE IF NOT EXISTS users ( id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT UNIQUE, password TEXT, role TEXT ) """) # إنشاء جدول الشكاوى (لو مش موجود) conn.execute(""" CREATE TABLE IF NOT EXISTS complaints ( id INTEGER PRIMARY KEY AUTOINCREMENT, complaint_id TEXT UNIQUE, username TEXT, complaint_text TEXT, status TEXT, response TEXT, timestamp TEXT, sender_comment TEXT DEFAULT '' ) """) # ✅ التأكد من وجود عمود sender_comment (وإضافته لو ناقص) try: columns = [col[1] for col in conn.execute("PRAGMA table_info(complaints)").fetchall()] if "sender_comment" not in columns: conn.execute("ALTER TABLE complaints ADD COLUMN sender_comment TEXT DEFAULT ''") conn.commit() except Exception as e: st.error(f"⚠️ خطأ أثناء التأكد من الأعمدة: {e}") # إنشاء جدول معلومات قاعدة البيانات conn.execute(""" CREATE TABLE IF NOT EXISTS db_info ( version INTEGER PRIMARY KEY ) """) # إدراج الإصدار الأول إذا لم يكن موجوداً conn.execute(""" INSERT OR IGNORE INTO db_info (version) VALUES (1) """) conn.commit() conn.close() # إدارة حالة الجلسة def init_session(): if "auth" not in st.session_state: st.session_state.auth = { "is_logged_in": False, "username": "", "role": "" } init_session() # واجهة تسجيل الدخول def login_page(): st.title("🔐 تسجيل الدخول") username = st.text_input("اسم المستخدم") password = st.text_input("كلمة المرور", type="password") if st.button("تسجيل الدخول"): conn = get_db_connection() user = conn.execute("SELECT * FROM users WHERE username = ?", (username,)).fetchone() conn.close() if user and bcrypt.verify(password, user["password"]): st.session_state.auth = { "is_logged_in": True, "username": user["username"], "role": user["role"] } st.rerun() elif user: st.error("❌ كلمة المرور غير صحيحة") else: st.warning("❌ اسم المستخدم غير موجود") # صفحة مقدم الشكاوى def sender_page(): st.title("✉️ تقديم شكوى جديدة") conn = get_db_connection() username = st.session_state.auth["username"] try: user_complaint_count = conn.execute( "SELECT COUNT(*) FROM complaints WHERE username = ?", (username,) ).fetchone()[0] complaint_id = f"{username}_{user_complaint_count + 1:06d}" complaint_text = st.text_area("📝 اكتب شكواك هنا", key="complaint_input") if st.button("📨 إرسال الشكوى"): if complaint_text.strip(): timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") conn.execute( "INSERT INTO complaints (complaint_id, username, complaint_text, status, response, timestamp, sender_comment) VALUES (?, ?, ?, ?, ?, ?, ?)", (complaint_id, username, complaint_text.strip(), "Pending", "", timestamp, "") ) conn.commit() st.success(f"✅ تم إرسال الشكوى بنجاح. معرف الشكوى هو: {complaint_id}") st.rerun() else: st.warning("⚠️ لا يمكن إرسال شكوى فارغة") st.subheader("📋 الشكاوى السابقة") complaints = conn.execute( "SELECT * FROM complaints WHERE username = ? ORDER BY id DESC", (username,) ).fetchall() for complaint in complaints: with st.expander(f"📨 {complaint['complaint_id']} | الحالة: {complaint['status']}"): st.write(f"📅 تم الإرسال في: {complaint['timestamp']}") st.write(f"📄 الشكوى: {complaint['complaint_text']}") if complaint['response']: st.success(f"💬 الرد من المسؤول: {complaint['response']}") st.toast(f"📬 تم الرد على الشكوى رقم {complaint['complaint_id']}") comment_key = f"comment_{complaint['complaint_id']}" sender_comment = st.text_area("🗨️ تعليقك على الرد", value=complaint['sender_comment'] or "", key=comment_key) if st.button("💬 حفظ التعليق", key=f"save_comment_{complaint['complaint_id']}"): if sender_comment.strip(): conn.execute( "UPDATE complaints SET sender_comment = ? WHERE complaint_id = ?", (sender_comment.strip(), complaint['complaint_id']) ) conn.commit() st.success("✅ تم حفظ تعليقك على الرد") st.rerun() finally: conn.close() # صفحة مستقبل الشكاوى مع لوحة التحكم الإدارية المحمية def receiver_page(): st.title("📬 إدارة الشكاوى") tab1, tab2 = st.tabs(["إدارة الشكاوى", "لوحة التحكم الإدارية"]) with tab1: conn = get_db_connection() try: pending_count = conn.execute( "SELECT COUNT(*) FROM complaints WHERE status = 'Pending'" ).fetchone()[0] if pending_count > 0: st.warning(f"🚨 يوجد {pending_count} شكوى جديدة لم يتم التعامل معها!") complaints = conn.execute( "SELECT * FROM complaints ORDER BY id DESC" ).fetchall() if not complaints: st.info("لا توجد شكاوى حالياً.") else: st.subheader("📋 جميع الشكاوى") selected_complaint = st.selectbox( "اختر شكوى للتعامل معها", complaints, format_func=lambda x: f"{x['complaint_id']} - {x['username']}" ) st.subheader(f"📨 معرف الشكوى: {selected_complaint['complaint_id']}") st.write(f"👤 مقدم الشكوى: {selected_complaint['username']}") st.write(f"📝 نص الشكوى: {selected_complaint['complaint_text']}") st.write(f"📅 وقت الإرسال: {selected_complaint['timestamp']}") new_status = st.selectbox( "🔄 تحديث الحالة", ["Pending", "In Progress", "Resolved"], index=["Pending", "In Progress", "Resolved"].index(selected_complaint["status"]) ) new_response = st.text_area( "💬 الرد على الشكوى", value=selected_complaint["response"] or "" ) if st.button("💾 حفظ التعديلات"): conn.execute( "UPDATE complaints SET status = ?, response = ? WHERE complaint_id = ?", (new_status, new_response.strip(), selected_complaint["complaint_id"]) ) conn.commit() st.success("✅ تم حفظ التعديلات بنجاح") st.rerun() finally: conn.close() with tab2: st.title("⚙️ لوحة التحكم الإدارية") admin_pass = st.text_input("أدخل كلمة المرور الإدارية:", type="password", key="admin_pass") if admin_pass == ADMIN_DB_PASSWORD: st.success("✅ تم المصادقة بنجاح") if os.path.exists("complaintsBD.db"): with open("complaintsBD.db", "rb") as db_file: st.download_button( label="📥 تحميل نسخة احتياطية", data=db_file, file_name=f"complaints_backup_{datetime.now().strftime('%Y%m%d')}.db", mime="application/octet-stream" ) if st.button("🔄 إنشاء نسخة احتياطية جديدة"): backup_name = f"backup_{datetime.now().strftime('%Y%m%d_%H%M')}.db" shutil.copy2("complaintsBD.db", backup_name) st.success(f"تم إنشاء النسخة الاحتياطية: {backup_name}") elif admin_pass: st.error("❌ كلمة المرور الإدارية غير صحيحة") # الواجهة الرئيسية def main(): init_db() # تهيئة قاعدة البيانات # ✅ طباعة مسار قاعدة البيانات للتأكد st.write("📂 Database path:", os.path.abspath("complaintsBD.db")) if not st.session_state.auth["is_logged_in"]: login_page() else: if st.session_state.auth["role"] == "sender": sender_page() else: receiver_page() st.markdown("---") if st.button("🚪 تسجيل الخروج"): st.session_state.auth = { "is_logged_in": False, "username": "", "role": "" } st.rerun() if __name__ == "__main__": main()