diff --git a/charity-settings.php b/charity-settings.php index 63c0164..351824f 100644 --- a/charity-settings.php +++ b/charity-settings.php @@ -1,20 +1,31 @@ query("UPDATE smtp_settings SET is_enabled = 1, consecutive_failures = 0 WHERE id = 1"); + $success_msg = 'تم إعادة تفعيل SMTP وتصفير عداد الأخطاء'; +} + // Fetch charity settings $stmt = db()->query("SELECT * FROM charity_settings WHERE id = 1"); $charity = $stmt->fetch(); -if ($_SERVER['REQUEST_METHOD'] === 'POST') { +// Fetch SMTP settings +$stmt = db()->query("SELECT * FROM smtp_settings WHERE id = 1"); +$smtp = $stmt->fetch(); + +// Handle Charity Settings Update +if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['update_charity'])) { $charity_name = $_POST['charity_name']; $charity_email = $_POST['charity_email']; $charity_phone = $_POST['charity_phone']; @@ -25,7 +36,6 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { $upload_dir = 'uploads/charity/'; if (!is_dir($upload_dir)) mkdir($upload_dir, 0775, true); - // Handle Logo Upload if (isset($_FILES['charity_logo']) && $_FILES['charity_logo']['error'] === UPLOAD_ERR_OK) { $file_ext = pathinfo($_FILES['charity_logo']['name'], PATHINFO_EXTENSION); $new_logo = 'logo_' . time() . '.' . $file_ext; @@ -34,7 +44,6 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { } } - // Handle Favicon Upload if (isset($_FILES['charity_favicon']) && $_FILES['charity_favicon']['error'] === UPLOAD_ERR_OK) { $file_ext = pathinfo($_FILES['charity_favicon']['name'], PATHINFO_EXTENSION); $new_favicon = 'favicon_' . time() . '.' . $file_ext; @@ -46,72 +55,343 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { $stmt = db()->prepare("UPDATE charity_settings SET charity_name = ?, charity_email = ?, charity_phone = ?, charity_address = ?, charity_logo = ?, charity_favicon = ? WHERE id = 1"); $stmt->execute([$charity_name, $charity_email, $charity_phone, $charity_address, $charity_logo, $charity_favicon]); $success_msg = 'تم تحديث إعدادات الجمعية بنجاح'; - - // Refresh charity data $stmt = db()->query("SELECT * FROM charity_settings WHERE id = 1"); $charity = $stmt->fetch(); } + +// Handle SMTP Settings Update +if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['update_smtp'])) { + $stmt = db()->prepare("UPDATE smtp_settings SET smtp_host = ?, smtp_port = ?, smtp_secure = ?, smtp_user = ?, smtp_pass = ?, from_email = ?, from_name = ?, reply_to = ?, max_failures = ? WHERE id = 1"); + $stmt->execute([ + $_POST['smtp_host'], + (int)$_POST['smtp_port'], + $_POST['smtp_secure'], + $_POST['smtp_user'], + $_POST['smtp_pass'], + $_POST['from_email'], + $_POST['from_name'], + $_POST['reply_to'], + (int)$_POST['max_failures'] + ]); + $success_msg = 'تم تحديث إعدادات البريد (SMTP) بنجاح'; + $stmt = db()->query("SELECT * FROM smtp_settings WHERE id = 1"); + $smtp = $stmt->fetch(); +} + +// Handle Test Email +if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['test_email_addr'])) { + $to = $_POST['test_email_addr']; + $res = MailService::sendMail($to, "رسالة تجريبية - Test Email", "

إذا كنت ترى هذه الرسالة، فإن إعدادات SMTP تعمل بشكل صحيح.

"); + if ($res['success']) { + $success_msg = "تم إرسال الرسالة التجريبية بنجاح إلى $to"; + } else { + $error_msg = "فشل إرسال الرسالة التجريبية: " . $res['error']; + } +} + +// Handle Status Operations +if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['add_status'])) { + $name = $_POST['status_name']; + $color = $_POST['status_color']; + $is_default = isset($_POST['is_default']) ? 1 : 0; + if ($is_default) db()->query("UPDATE mailbox_statuses SET is_default = 0"); + $stmt = db()->prepare("INSERT INTO mailbox_statuses (name, color, is_default) VALUES (?, ?, ?)"); + $stmt->execute([$name, $color, $is_default]); + $success_msg = 'تم إضافة نوع الحالة بنجاح'; +} + +if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['update_status'])) { + $id = $_POST['status_id']; + $name = $_POST['status_name']; + $color = $_POST['status_color']; + $is_default = isset($_POST['is_default']) ? 1 : 0; + if ($is_default) db()->query("UPDATE mailbox_statuses SET is_default = 0"); + $stmt = db()->prepare("UPDATE mailbox_statuses SET name = ?, color = ?, is_default = ? WHERE id = ?"); + $stmt->execute([$name, $color, $is_default, $id]); + $success_msg = 'تم تحديث نوع الحالة بنجاح'; +} + +if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['delete_status'])) { + $id = $_POST['status_id']; + $count = db()->prepare("SELECT COUNT(*) FROM mailbox WHERE status_id = ?"); + $count->execute([$id]); + if ($count->fetchColumn() > 0) { + $error_msg = 'لا يمكن حذف هذه الحالة لأنها مستخدمة في بعض السجلات'; + } else { + db()->prepare("DELETE FROM mailbox_statuses WHERE id = ?")->execute([$id]); + $success_msg = 'تم حذف نوع الحالة بنجاح'; + } +} + +$statuses = db()->query("SELECT * FROM mailbox_statuses ORDER BY id ASC")->fetchAll(); +$email_logs = db()->query("SELECT * FROM email_logs ORDER BY id DESC LIMIT 50")->fetchAll(); ?>
-

إعدادات الجمعية

+

الإعدادات

+ +
+ -
-
-

بيانات الجمعية

-
-
-
- - +
+ + +
+ +
+

بيانات الجمعية

+ + +
+
+ + +
+
+ + +
-
- - +
+ +
-
- -
- - +
+ + +
+
+
+ + + +
Logo
+ +
+
+ + + +
Favicon
+ +
+
+ + +
+ + +
+
+

إعدادات البريد (SMTP)

+ +
+ SMTP معطل بسبب كثرة الأخطاء +
+ +
+
+ +
+ SMTP مفعل (أخطاء: /) +
+
-
- - -
+
+ +
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ + +
+
+
+ + +
+
+ + +
+
+
+ + +
+
+ + +
+
+ + +
+
+ +
-
-
- - - -
- Logo +
+
اختبار الإرسال
+
+
+ + +
+
+
+ + +
+

أنواع حالات البريد

+
+ +
+
+ + +
+
+ + +
+
+
+ +
- -
-
- - - -
- Favicon -
- +
+
+ +
+
+
+ + + + + + + + + + + + + + +
الاسماللونافتراضيةالإجراء
' : '' ?> + +
+
+
- + +
+

سجلات البريد المرسل (آخر 50 عملية)

+
+ + + + + + + + + + + + + + + + + + + + + +
الوقتالمستلمالموضوعالحالةالخطأ
+ + + +
+
+
+
+
+
+ + - + + + \ No newline at end of file diff --git a/db/migrations/004_add_mailbox_statuses.sql b/db/migrations/004_add_mailbox_statuses.sql new file mode 100644 index 0000000..54d7cc3 --- /dev/null +++ b/db/migrations/004_add_mailbox_statuses.sql @@ -0,0 +1,25 @@ +-- Migration: Add mailbox statuses table +CREATE TABLE IF NOT EXISTS mailbox_statuses ( + id INT AUTO_INCREMENT PRIMARY KEY, + name VARCHAR(50) NOT NULL, + color VARCHAR(20) DEFAULT '#000000', + is_default BOOLEAN DEFAULT FALSE, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- Insert initial statuses if they don't exist +INSERT IGNORE INTO mailbox_statuses (id, name, color, is_default) VALUES +(1, 'received', '#6c757d', TRUE), +(2, 'in_progress', '#0d6efd', FALSE), +(3, 'closed', '#198754', FALSE); + +-- Add status_id to mailbox +ALTER TABLE mailbox ADD COLUMN IF NOT EXISTS status_id INT; + +-- Update status_id based on existing ENUM values +UPDATE mailbox SET status_id = 1 WHERE status = 'received' AND status_id IS NULL; +UPDATE mailbox SET status_id = 2 WHERE status = 'in_progress' AND status_id IS NULL; +UPDATE mailbox SET status_id = 3 WHERE status = 'closed' AND status_id IS NULL; + +-- Set default status_id for any NULLs +UPDATE mailbox SET status_id = 1 WHERE status_id IS NULL; diff --git a/db/migrations/005_add_due_date_to_mailbox.sql b/db/migrations/005_add_due_date_to_mailbox.sql new file mode 100644 index 0000000..f6faa70 --- /dev/null +++ b/db/migrations/005_add_due_date_to_mailbox.sql @@ -0,0 +1,2 @@ +-- Migration: Add due_date column to mailbox table +ALTER TABLE mailbox ADD COLUMN IF NOT EXISTS due_date DATE NULL; diff --git a/db/migrations/006_add_smtp_settings.sql b/db/migrations/006_add_smtp_settings.sql new file mode 100644 index 0000000..4fdb168 --- /dev/null +++ b/db/migrations/006_add_smtp_settings.sql @@ -0,0 +1,18 @@ +CREATE TABLE IF NOT EXISTS smtp_settings ( + id INT AUTO_INCREMENT PRIMARY KEY, + transport VARCHAR(20) DEFAULT 'smtp', + smtp_host VARCHAR(255), + smtp_port INT DEFAULT 587, + smtp_secure VARCHAR(10) DEFAULT 'tls', + smtp_user VARCHAR(255), + smtp_pass VARCHAR(255), + from_email VARCHAR(255), + from_name VARCHAR(255), + reply_to VARCHAR(255), + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +-- Insert default row if not exists +INSERT INTO smtp_settings (id, transport, smtp_host, smtp_port, smtp_secure, from_email, from_name) +SELECT 1, 'smtp', '', 587, 'tls', 'no-reply@localhost', 'App' +WHERE NOT EXISTS (SELECT 1 FROM smtp_settings WHERE id = 1); diff --git a/db/migrations/007_add_email_logs.sql b/db/migrations/007_add_email_logs.sql new file mode 100644 index 0000000..602591a --- /dev/null +++ b/db/migrations/007_add_email_logs.sql @@ -0,0 +1,14 @@ +-- Create email_logs table +CREATE TABLE IF NOT EXISTS email_logs ( + id INT AUTO_INCREMENT PRIMARY KEY, + recipient TEXT NOT NULL, + subject VARCHAR(255), + status ENUM('success', 'failure') NOT NULL, + error_message TEXT, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP +); + +-- Add consecutive_failures to smtp_settings to track repeated issues +ALTER TABLE smtp_settings ADD COLUMN consecutive_failures INT DEFAULT 0; +ALTER TABLE smtp_settings ADD COLUMN max_failures INT DEFAULT 5; +ALTER TABLE smtp_settings ADD COLUMN is_enabled TINYINT(1) DEFAULT 1; diff --git a/inbound.php b/inbound.php index cc1dbef..37e7aff 100644 --- a/inbound.php +++ b/inbound.php @@ -1,8 +1,48 @@ query("SELECT * FROM mailbox_statuses ORDER BY id ASC")->fetchAll(); +$default_status_id = db()->query("SELECT id FROM mailbox_statuses WHERE is_default = 1 LIMIT 1")->fetchColumn() ?: 1; + +// Function to send assignment notification +function sendAssignmentNotification($assigned_to_id, $ref_no, $subject) { + if (!$assigned_to_id) return; + + $stmt = db()->prepare("SELECT full_name, email FROM users WHERE id = ?"); + $stmt->execute([$assigned_to_id]); + $user = $stmt->fetch(); + + if ($user && !empty($user['email'])) { + $to = $user['email']; + $email_subject = "تنبيه: تم تعيين بريد جديد لك (رقم القيد: $ref_no)"; + $htmlBody = " +
+

مرحباً " . htmlspecialchars($user['full_name']) . "

+

لقد تم تعيين مهمة بريد جديد لك في النظام.

+ + + + + + + + + +
رقم القيد" . htmlspecialchars($ref_no) . "
الموضوع" . htmlspecialchars($subject) . "
+

يرجى الدخول للنظام لمتابعة المهمة.

+
+

هذا تنبيه تلقائي، يرجى عدم الرد.

+
+ "; + MailService::sendMail($to, $email_subject, $htmlBody); + } +} // Handle actions if ($_SERVER['REQUEST_METHOD'] === 'POST') { @@ -10,23 +50,39 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { $type = 'inbound'; $ref_no = $_POST['ref_no'] ?? ''; $date_registered = $_POST['date_registered'] ?? date('Y-m-d'); + $due_date = !empty($_POST['due_date']) ? $_POST['due_date'] : null; $sender = $_POST['sender'] ?? ''; $recipient = $_POST['recipient'] ?? ''; $subject = $_POST['subject'] ?? ''; $description = $_POST['description'] ?? ''; - $status = $_POST['status'] ?? 'received'; + $status_id = $_POST['status_id'] ?? $default_status_id; $assigned_to = !empty($_POST['assigned_to']) ? $_POST['assigned_to'] : null; $id = $_POST['id'] ?? 0; if ($ref_no && $subject) { try { if ($action === 'add') { - $stmt = db()->prepare("INSERT INTO mailbox (type, ref_no, date_registered, sender, recipient, subject, description, status, assigned_to, created_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); - $stmt->execute([$type, $ref_no, $date_registered, $sender, $recipient, $subject, $description, $status, $assigned_to, $_SESSION['user_id']]); + $stmt = db()->prepare("INSERT INTO mailbox (type, ref_no, date_registered, due_date, sender, recipient, subject, description, status_id, assigned_to, created_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); + $stmt->execute([$type, $ref_no, $date_registered, $due_date, $sender, $recipient, $subject, $description, $status_id, $assigned_to, $user_id]); + + if ($assigned_to) { + sendAssignmentNotification($assigned_to, $ref_no, $subject); + } + $success = 'تمت إضافة البريد بنجاح'; } elseif ($action === 'edit') { - $stmt = db()->prepare("UPDATE mailbox SET ref_no = ?, date_registered = ?, sender = ?, recipient = ?, subject = ?, description = ?, status = ?, assigned_to = ? WHERE id = ? AND type = 'inbound'"); - $stmt->execute([$ref_no, $date_registered, $sender, $recipient, $subject, $description, $status, $assigned_to, $id]); + // Get previous assigned_to to check if it changed + $stmt_old = db()->prepare("SELECT assigned_to FROM mailbox WHERE id = ?"); + $stmt_old->execute([$id]); + $old_assigned_to = $stmt_old->fetchColumn(); + + $stmt = db()->prepare("UPDATE mailbox SET ref_no = ?, date_registered = ?, due_date = ?, sender = ?, recipient = ?, subject = ?, description = ?, status_id = ?, assigned_to = ? WHERE id = ? AND type = 'inbound'"); + $stmt->execute([$ref_no, $date_registered, $due_date, $sender, $recipient, $subject, $description, $status_id, $assigned_to, $id]); + + if ($assigned_to && $assigned_to != $old_assigned_to) { + sendAssignmentNotification($assigned_to, $ref_no, $subject); + } + $success = 'تم تحديث البيانات بنجاح'; } } catch (PDOException $e) { @@ -50,13 +106,28 @@ if (isset($_GET['action']) && $_GET['action'] === 'delete' && isset($_GET['id']) } $search = $_GET['search'] ?? ''; -$query = "SELECT * FROM mailbox WHERE type = 'inbound'"; +$my_tasks = isset($_GET['my_tasks']) && $_GET['my_tasks'] == 1; + +$query = "SELECT m.*, s.name as status_name, s.color as status_color, u.full_name as assigned_to_name + FROM mailbox m + LEFT JOIN mailbox_statuses s ON m.status_id = s.id + LEFT JOIN users u ON m.assigned_to = u.id + WHERE m.type = 'inbound'"; $params = []; + if ($search) { - $query .= " AND (ref_no LIKE ? OR sender LIKE ? OR subject LIKE ?)"; - $params = ["%$search%", "%$search%", "%$search%"]; + $query .= " AND (m.ref_no LIKE ? OR m.sender LIKE ? OR m.subject LIKE ?)"; + $params[] = "%$search%"; + $params[] = "%$search%"; + $params[] = "%$search%"; } -$query .= " ORDER BY created_at DESC"; + +if ($my_tasks) { + $query .= " AND m.assigned_to = ?"; + $params[] = $user_id; +} + +$query .= " ORDER BY m.created_at DESC"; $stmt = db()->prepare($query); $stmt->execute($params); $mails = $stmt->fetchAll(); @@ -70,6 +141,19 @@ if (isset($_GET['action']) && $_GET['action'] === 'edit' && isset($_GET['id'])) $stmt->execute([$_GET['id']]); $deepLinkData = $stmt->fetch(); } + +function getStatusBadgeInList($mail) { + $status_name = $mail['status_name'] ?? 'غير معروف'; + $status_color = $mail['status_color'] ?? '#6c757d'; + + // Translation for default statuses + $display_name = $status_name; + if ($status_name == 'received') $display_name = 'تم الاستلام'; + if ($status_name == 'in_progress') $display_name = 'قيد المعالجة'; + if ($status_name == 'closed') $display_name = 'مكتمل'; + + return '' . htmlspecialchars($display_name) . ''; +} ?>
@@ -95,13 +179,24 @@ if (isset($_GET['action']) && $_GET['action'] === 'edit' && isset($_GET['id']))
-
+
-
- +
+
+ onchange="this.form.submit()"> + +
+
+ +
+ + +
@@ -111,8 +206,10 @@ if (isset($_GET['action']) && $_GET['action'] === 'edit' && isset($_GET['id'])) رقم القيد التاريخ + الموعد النهائي الموضوع المرسل + المسؤول الحالة الإجراءات @@ -122,21 +219,32 @@ if (isset($_GET['action']) && $_GET['action'] === 'edit' && isset($_GET['id'])) + + + + + + + + + + - + + - - تم الاستلام - - قيد المعالجة - - مكتمل + + + + غير معين + @@ -144,7 +252,7 @@ if (isset($_GET['action']) && $_GET['action'] === 'edit' && isset($_GET['id'])) - لا يوجد بريد وارد مسجل حالياً + لا يوجد بريد وارد مسجل حالياً @@ -167,14 +275,18 @@ if (isset($_GET['action']) && $_GET['action'] === 'edit' && isset($_GET['id']))
-
+
-
+
+
+ + +
@@ -193,10 +305,16 @@ if (isset($_GET['action']) && $_GET['action'] === 'edit' && isset($_GET['id']))
- + + + +
@@ -240,11 +358,12 @@ function openMailModal(action, data = null) { const fields = { ref_no: document.getElementById('modalRefNo'), date_registered: document.getElementById('modalDateRegistered'), + due_date: document.getElementById('modalDueDate'), sender: document.getElementById('modalSender'), recipient: document.getElementById('modalRecipient'), subject: document.getElementById('modalSubject'), description: document.getElementById('modalDescription'), - status: document.getElementById('modalStatus'), + status_id: document.getElementById('modalStatusId'), assigned_to: document.getElementById('modalAssignedTo') }; @@ -255,7 +374,7 @@ function openMailModal(action, data = null) { modalId.value = '0'; Object.keys(fields).forEach(key => { if (key === 'date_registered') fields[key].value = ''; - else if (key === 'status') fields[key].value = 'received'; + else if (key === 'status_id') fields[key].value = ''; else fields[key].value = ''; }); } else { @@ -277,11 +396,12 @@ document.addEventListener('DOMContentLoaded', function() { 'id' => $_POST['id'] ?? 0, 'ref_no' => $_POST['ref_no'] ?? '', 'date_registered' => $_POST['date_registered'] ?? date('Y-m-d'), + 'due_date' => $_POST['due_date'] ?? '', 'sender' => $_POST['sender'] ?? '', 'recipient' => $_POST['recipient'] ?? '', 'subject' => $_POST['subject'] ?? '', 'description' => $_POST['description'] ?? '', - 'status' => $_POST['status'] ?? 'received', + 'status_id' => $_POST['status_id'] ?? $default_status_id, 'assigned_to' => $_POST['assigned_to'] ?? '' ]) ?>; openMailModal('', errorData); diff --git a/includes/header.php b/includes/header.php index 7ce0fbe..501fe57 100644 --- a/includes/header.php +++ b/includes/header.php @@ -44,16 +44,16 @@ if (isLoggedIn()) { - + - + - + - + - + \ No newline at end of file diff --git a/overdue_report.php b/overdue_report.php new file mode 100644 index 0000000..879ad71 --- /dev/null +++ b/overdue_report.php @@ -0,0 +1,126 @@ +prepare($sql); +$stmt->execute($params); +$overdue_items = $stmt->fetchAll(); + +// Fetch all users for filter +$users = db()->query("SELECT id, full_name FROM users ORDER BY full_name")->fetchAll(); +?> + +
+

تقرير المهام المتأخرة

+
+ +
+
+
+
+ + +
+
+ + +
+
+ +
+
+
+
+ +
+
+
جميع المهام المتأخرة
+
+
+
+ + + + + + + + + + + + + + + + + + + diff($due_date)->format("%a"); + ?> + + + + + + + + + + + + +
رقم المرجعالنوعالموضوعالموظف المسؤولتاريخ الاستحقاقالأيام المتأخرةالإجراءات
لا توجد مهام متأخرة حالياً.
+ + + + يوم + + عرض + +
+
+
+
+ + diff --git a/scripts/send_reminders.php b/scripts/send_reminders.php new file mode 100644 index 0000000..8e78f39 --- /dev/null +++ b/scripts/send_reminders.php @@ -0,0 +1,75 @@ +query(" + SELECT m.*, u.email, u.full_name + FROM mailbox m + JOIN users u ON m.assigned_to = u.id + WHERE m.due_date = DATE_ADD(CURDATE(), INTERVAL 1 DAY) + AND m.status != 'closed' +")->fetchAll(); + +foreach ($due_tomorrow as $task) { + if (!empty($task['email'])) { + $subject = "تذكير: موعد نهائي لمهمة غداً - " . $task['ref_no']; + $html = " +

تذكير بموعد نهائي

+

عزيزي " . htmlspecialchars($task['full_name']) . "،

+

هذا تذكير بأن المهمة التالية مستحقة غداً:

+
    +
  • رقم المرجع: " . htmlspecialchars($task['ref_no']) . "
  • +
  • الموضوع: " . htmlspecialchars($task['subject']) . "
  • +
  • تاريخ الاستحقاق: " . $task['due_date'] . "
  • +
+

يرجى متابعة المهمة وإغلاقها في الوقت المحدد.

+ "; + $res = MailService::sendMail($task['email'], $subject, $html); + if ($res['success']) { + echo "Sent 24h reminder to " . $task['email'] . " for task " . $task['ref_no'] . PHP_EOL; + } else { + echo "Failed to send 24h reminder to " . $task['email'] . ": " . ($res['error'] ?? 'Unknown error') . PHP_EOL; + } + } +} + +// 2. Overdue tasks (due date passed and still not closed) - Only send once a week or daily? +// For now, let's send daily for overdue tasks to ensure they are handled. +$overdue = db()->query(" + SELECT m.*, u.email, u.full_name + FROM mailbox m + JOIN users u ON m.assigned_to = u.id + WHERE m.due_date < CURDATE() + AND m.status != 'closed' +")->fetchAll(); + +foreach ($overdue as $task) { + if (!empty($task['email'])) { + $subject = "تنبيه: مهمة متأخرة! - " . $task['ref_no']; + $html = " +

تنبيه: مهمة متأخرة

+

عزيزي " . htmlspecialchars($task['full_name']) . "،

+

هذه المهمة قد تجاوزت الموعد النهائي المحدد:

+
    +
  • رقم المرجع: " . htmlspecialchars($task['ref_no']) . "
  • +
  • الموضوع: " . htmlspecialchars($task['subject']) . "
  • +
  • تاريخ الاستحقاق: " . $task['due_date'] . "
  • +
+

يرجى معالجة هذه المهمة في أقرب وقت ممكن.

+ "; + $res = MailService::sendMail($task['email'], $subject, $html); + if ($res['success']) { + echo "Sent overdue reminder to " . $task['email'] . " for task " . $task['ref_no'] . PHP_EOL; + } else { + echo "Failed to send overdue reminder to " . $task['email'] . ": " . ($res['error'] ?? 'Unknown error') . PHP_EOL; + } + } +} + +echo "[" . date('Y-m-d H:i:s') . "] Reminder process finished." . PHP_EOL; diff --git a/user_dashboard.php b/user_dashboard.php new file mode 100644 index 0000000..6824c03 --- /dev/null +++ b/user_dashboard.php @@ -0,0 +1,290 @@ +prepare("SELECT COUNT(*) FROM mailbox WHERE assigned_to = ?"); +$stmt->execute([$user_id]); +$my_total_assignments = $stmt->fetchColumn(); + +$stmt = db()->prepare("SELECT COUNT(*) FROM mailbox WHERE assigned_to = ? AND status != 'closed'"); +$stmt->execute([$user_id]); +$my_pending_tasks = $stmt->fetchColumn(); + +// Global Stats (for Clerks or if we want to show them) +$total_inbound = db()->query("SELECT COUNT(*) FROM mailbox WHERE type = 'inbound'")->fetchColumn(); +$total_outbound = db()->query("SELECT COUNT(*) FROM mailbox WHERE type = 'outbound'")->fetchColumn(); + +// Fetch statuses for badge and count +$statuses_data = db()->query("SELECT * FROM mailbox_statuses")->fetchAll(PDO::FETCH_UNIQUE); + +// My Assignments +$my_assignments = db()->prepare("SELECT m.*, s.name as status_name, s.color as status_color + FROM mailbox m + LEFT JOIN mailbox_statuses s ON m.status_id = s.id + WHERE m.assigned_to = ? + ORDER BY m.created_at DESC LIMIT 10"); +$my_assignments->execute([$user_id]); +$my_assignments = $my_assignments->fetchAll(); + +// Recent Activity +$recent_query = "SELECT m.*, s.name as status_name, s.color as status_color, u.full_name as assigned_to_name + FROM mailbox m + LEFT JOIN mailbox_statuses s ON m.status_id = s.id + LEFT JOIN users u ON m.assigned_to = u.id"; + +if ($is_clerk) { + // Clerks see all recent activity + $recent_stmt = db()->prepare($recent_query . " ORDER BY m.updated_at DESC LIMIT 10"); + $recent_stmt->execute(); +} else { + // Staff see only theirs + $recent_stmt = db()->prepare($recent_query . " WHERE m.assigned_to = ? OR m.created_by = ? ORDER BY m.updated_at DESC LIMIT 10"); + $recent_stmt->execute([$user_id, $user_id]); +} +$recent_activity = $recent_stmt->fetchAll(); + +function getStatusBadge($mail) { + $status_name = $mail['status_name'] ?? 'غير معروف'; + $status_color = $mail['status_color'] ?? '#6c757d'; + + $display_name = $status_name; + if ($status_name == 'received') $display_name = 'تم الاستلام'; + if ($status_name == 'in_progress') $display_name = 'قيد المعالجة'; + if ($status_name == 'closed') $display_name = 'مكتمل'; + + return '' . htmlspecialchars($display_name) . ''; +} +?> + +
+
+
+
+ +
+
+
+

مرحباً، !

+

+ + أنت مسجل كـ كاتب. يمكنك متابعة كافة المراسلات وإدارة المهام. + + أنت مسجل كـ موظف. تابع مهامك المسندة إليك هنا. + +

+
+
+ + Profile + +
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+
+ +
+
+
مهامي
+

+
+
+
+
+
+
+
+
+ +
+
+
قيد التنفيذ
+

+
+
+
+
+ + + +
+
+
+
+ +
+
+
إجمالي الوارد
+

+
+
+
+
+
+
+
+
+ +
+
+
إجمالي الصادر
+

+
+
+
+
+ + +
+
+
+
+ +
+
+
وارد من قبلي
+ prepare("SELECT COUNT(*) FROM mailbox WHERE created_by = ? AND type = 'inbound'"); + $stmt->execute([$user_id]); + $my_in_count = $stmt->fetchColumn(); + ?> +

+
+
+
+
+
+
+
+
+ +
+
+
صادر من قبلي
+ prepare("SELECT COUNT(*) FROM mailbox WHERE created_by = ? AND type = 'outbound'"); + $stmt->execute([$user_id]); + $my_out_count = $stmt->fetchColumn(); + ?> +

+
+
+
+
+ +
+ +
+ +
+
+
+
مهامي المسندة
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
رقم القيدالموضوعالموعد النهائيالحالةالإجراء
+ + + + + + - + + + عرض +
+ + أنت على اطلاع بكافة مهامك! لا توجد مهام معلقة. +
+
+
+
+
+ + +
+
+
+
+
+
+
+ + + +
+
+ +
+
+ + + + + +
+
+ + +
+ لا يوجد نشاط مسجل +
+ +
+
+ +
+
+
+ + \ No newline at end of file diff --git a/view_mail.php b/view_mail.php index 29a5088..3859a7a 100644 --- a/view_mail.php +++ b/view_mail.php @@ -4,10 +4,12 @@ require_once __DIR__ . '/includes/header.php'; $id = $_GET['id'] ?? 0; if (!$id) redirect('index.php'); -$stmt = db()->prepare("SELECT m.*, u1.full_name as assigned_name, u2.full_name as creator_name +$stmt = db()->prepare("SELECT m.*, u1.full_name as assigned_name, u2.full_name as creator_name, + s.name as status_name, s.color as status_color FROM mailbox m LEFT JOIN users u1 ON m.assigned_to = u1.id LEFT JOIN users u2 ON m.created_by = u2.id + LEFT JOIN mailbox_statuses s ON m.status_id = s.id WHERE m.id = ?"); $stmt->execute([$id]); $mail = $stmt->fetch(); @@ -116,24 +118,41 @@ function isPreviewable($fileName) {
-
+

-
+

-
+
+ +

+ + + + + + + + + غير محدد + +

+
+

- - تم الاستلام - - قيد المعالجة - - مكتمل - + +

@@ -281,7 +300,7 @@ function isPreviewable($fileName) {