Hadeeratef91's picture
Update app.py
ecec81d verified
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()