adding editor
This commit is contained in:
parent
6ddb4f9f37
commit
627842bf5c
687
inbound.php
687
inbound.php
@ -1,391 +1,301 @@
|
|||||||
<?php
|
<?php
|
||||||
require_once __DIR__ . '/includes/header.php';
|
require_once 'includes/header.php';
|
||||||
require_once __DIR__ . '/m_services/MailService.php';
|
|
||||||
|
|
||||||
// Check if user has view permission
|
|
||||||
if (!canView('inbound')) {
|
|
||||||
redirect('index.php');
|
|
||||||
}
|
|
||||||
|
|
||||||
$error = '';
|
$error = '';
|
||||||
$success = '';
|
$success = '';
|
||||||
$user_id = $_SESSION['user_id'];
|
|
||||||
|
|
||||||
// Fetch statuses
|
// Handle CRUD operations
|
||||||
$statuses_list = db()->query("SELECT * FROM mailbox_statuses ORDER BY id ASC")->fetchAll();
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
|
||||||
$default_status_id = db()->query("SELECT id FROM mailbox_statuses WHERE is_default = 1 LIMIT 1")->fetchColumn() ?: 1;
|
if (!canEdit('inbound') && !canAdd('inbound')) {
|
||||||
|
$error = 'ليس لديك صلاحية للقيام بهذا الإجراء.';
|
||||||
// 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 = "
|
|
||||||
<div dir='rtl' style='font-family: Arial, sans-serif;'>
|
|
||||||
<h2>مرحباً " . htmlspecialchars($user['full_name']) . "</h2>
|
|
||||||
<p>لقد تم تعيين مهمة بريد جديد لك في النظام.</p>
|
|
||||||
<table border='1' cellpadding='10' cellspacing='0' style='border-collapse: collapse;'>
|
|
||||||
<tr>
|
|
||||||
<th style='background-color: #f8f9fa;'>رقم القيد</th>
|
|
||||||
<td>" . htmlspecialchars($ref_no) . "</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th style='background-color: #f8f9fa;'>الموضوع</th>
|
|
||||||
<td>" . htmlspecialchars($subject) . "</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<p>يرجى الدخول للنظام لمتابعة المهمة.</p>
|
|
||||||
<br>
|
|
||||||
<p>هذا تنبيه تلقائي، يرجى عدم الرد.</p>
|
|
||||||
</div>
|
|
||||||
";
|
|
||||||
MailService::sendMail($to, $email_subject, $htmlBody);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle actions
|
|
||||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
||||||
$action = $_POST['action'] ?? '';
|
|
||||||
|
|
||||||
// Permission checks for POST actions
|
|
||||||
if (($action === 'add' && !canAdd('inbound')) || ($action === 'edit' && !canEdit('inbound'))) {
|
|
||||||
$error = 'عذراً، ليس لديك الصلاحية للقيام بهذا الإجراء';
|
|
||||||
} else {
|
} else {
|
||||||
$type = 'inbound';
|
$action = $_POST['action'];
|
||||||
|
$id = $_POST['id'] ?? 0;
|
||||||
$ref_no = $_POST['ref_no'] ?? '';
|
$ref_no = $_POST['ref_no'] ?? '';
|
||||||
$date_registered = $_POST['date_registered'] ?? date('Y-m-d');
|
$date_registered = $_POST['date_registered'] ?? date('Y-m-d');
|
||||||
$due_date = !empty($_POST['due_date']) ? $_POST['due_date'] : null;
|
$due_date = $_POST['due_date'] ?? null;
|
||||||
$sender = $_POST['sender'] ?? '';
|
$sender = $_POST['sender'] ?? '';
|
||||||
$recipient = $_POST['recipient'] ?? '';
|
$recipient = $_POST['recipient'] ?? '';
|
||||||
$subject = $_POST['subject'] ?? '';
|
$subject = $_POST['subject'] ?? '';
|
||||||
$description = $_POST['description'] ?? '';
|
$description = $_POST['description'] ?? '';
|
||||||
$status_id = $_POST['status_id'] ?? $default_status_id;
|
$status_id = $_POST['status_id'] ?? null;
|
||||||
$assigned_to = !empty($_POST['assigned_to']) ? $_POST['assigned_to'] : null;
|
$assigned_to = $_POST['assigned_to'] ?? null;
|
||||||
$id = $_POST['id'] ?? 0;
|
|
||||||
|
|
||||||
if ($ref_no && $subject) {
|
if ($action === 'add' || $action === 'edit') {
|
||||||
$should_notify = false;
|
|
||||||
try {
|
try {
|
||||||
db()->beginTransaction();
|
db()->beginTransaction();
|
||||||
|
|
||||||
if ($action === 'add') {
|
if ($action === 'add') {
|
||||||
|
if (!canAdd('inbound')) throw new Exception('ليس لديك صلاحية الإضافة.');
|
||||||
$stmt = db()->prepare("INSERT INTO inbound_mail (ref_no, date_registered, due_date, sender, recipient, subject, description, status_id, assigned_to, created_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
$stmt = db()->prepare("INSERT INTO inbound_mail (ref_no, date_registered, due_date, sender, recipient, subject, description, status_id, assigned_to, created_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
||||||
$stmt->execute([$ref_no, $date_registered, $due_date, $sender, $recipient, $subject, $description, $status_id, $assigned_to, $user_id]);
|
$stmt->execute([$ref_no, $date_registered, $due_date, $sender, $recipient, $subject, $description, $status_id, $assigned_to, $_SESSION['user_id']]);
|
||||||
$mail_id = db()->lastInsertId();
|
$id = db()->lastInsertId();
|
||||||
|
$success = 'تم إضافة البريد الوارد بنجاح.';
|
||||||
if ($assigned_to) {
|
} else {
|
||||||
$should_notify = true;
|
if (!canEdit('inbound')) throw new Exception('ليس لديك صلاحية التعديل.');
|
||||||
}
|
|
||||||
|
|
||||||
$_SESSION['success'] = 'تمت إضافة البريد بنجاح';
|
|
||||||
} elseif ($action === 'edit') {
|
|
||||||
$mail_id = $id;
|
|
||||||
// Get previous assigned_to to check if it changed
|
|
||||||
$stmt_old = db()->prepare("SELECT assigned_to FROM inbound_mail WHERE id = ?");
|
|
||||||
$stmt_old->execute([$id]);
|
|
||||||
$old_assigned_to = $stmt_old->fetchColumn();
|
|
||||||
|
|
||||||
$stmt = db()->prepare("UPDATE inbound_mail SET ref_no = ?, date_registered = ?, due_date = ?, sender = ?, recipient = ?, subject = ?, description = ?, status_id = ?, assigned_to = ? WHERE id = ?");
|
$stmt = db()->prepare("UPDATE inbound_mail SET ref_no = ?, date_registered = ?, due_date = ?, sender = ?, recipient = ?, subject = ?, description = ?, status_id = ?, assigned_to = ? WHERE id = ?");
|
||||||
$stmt->execute([$ref_no, $date_registered, $due_date, $sender, $recipient, $subject, $description, $status_id, $assigned_to, $id]);
|
$stmt->execute([$ref_no, $date_registered, $due_date, $sender, $recipient, $subject, $description, $status_id, $assigned_to, $id]);
|
||||||
|
$success = 'تم تحديث بيانات البريد الوارد بنجاح.';
|
||||||
if ($assigned_to && $assigned_to != $old_assigned_to) {
|
|
||||||
$should_notify = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$_SESSION['success'] = 'تم تحديث البيانات بنجاح';
|
// Handle file uploads
|
||||||
}
|
if (isset($_FILES['attachments']) && !empty($_FILES['attachments']['name'][0])) {
|
||||||
|
|
||||||
// Handle Attachments
|
|
||||||
if (!empty($_FILES['attachments']['name'][0])) {
|
|
||||||
$upload_dir = 'uploads/attachments/';
|
$upload_dir = 'uploads/attachments/';
|
||||||
if (!is_dir($upload_dir)) mkdir($upload_dir, 0777, true);
|
if (!is_dir($upload_dir)) mkdir($upload_dir, 0777, true);
|
||||||
|
|
||||||
foreach ($_FILES['attachments']['name'] as $key => $name) {
|
for ($i = 0; $i < count($_FILES['attachments']['name']); $i++) {
|
||||||
if ($_FILES['attachments']['error'][$key] === 0) {
|
if ($_FILES['attachments']['error'][$i] === 0) {
|
||||||
$file_name = time() . '_' . basename($name);
|
$filename = time() . '_' . $_FILES['attachments']['name'][$i];
|
||||||
$target_path = $upload_dir . $file_name;
|
$filepath = $upload_dir . $filename;
|
||||||
if (move_uploaded_file($_FILES['attachments']['tmp_name'][$key], $target_path)) {
|
if (move_uploaded_file($_FILES['attachments']['tmp_name'][$i], $filepath)) {
|
||||||
$stmt = db()->prepare("INSERT INTO inbound_attachments (mail_id, display_name, file_path, file_name, file_size) VALUES (?, ?, ?, ?, ?)");
|
$stmt = db()->prepare("INSERT INTO inbound_attachments (mail_id, display_name, file_path, file_name, file_size) VALUES (?, ?, ?, ?, ?)");
|
||||||
$stmt->execute([$mail_id, $name, $target_path, $name, $_FILES['attachments']['size'][$key]]);
|
$stmt->execute([$id, $_FILES['attachments']['name'][$i], $filepath, $_FILES['attachments']['name'][$i], $_FILES['attachments']['size'][$i]]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
db()->commit();
|
db()->commit();
|
||||||
|
} catch (Exception $e) {
|
||||||
// Notify after commit to avoid holding locks during email sending
|
db()->rollBack();
|
||||||
if ($should_notify) {
|
$error = 'خطأ: ' . $e->getMessage();
|
||||||
sendAssignmentNotification($assigned_to, $ref_no, $subject);
|
|
||||||
}
|
}
|
||||||
|
} elseif ($action === 'delete') {
|
||||||
redirect('inbound.php');
|
|
||||||
} catch (PDOException $e) {
|
|
||||||
if (db()->inTransaction()) db()->rollBack();
|
|
||||||
if ($e->getCode() == 23000) {
|
|
||||||
$error = 'رقم القيد مستخدم مسبقاً';
|
|
||||||
} else {
|
|
||||||
$error = 'حدث خطأ: ' . $e->getMessage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$error = 'يرجى ملء الحقول المطلوبة (رقم القيد، الموضوع)';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete action
|
|
||||||
if (isset($_GET['action']) && $_GET['action'] === 'delete' && isset($_GET['id'])) {
|
|
||||||
if (!canDelete('inbound')) {
|
if (!canDelete('inbound')) {
|
||||||
$error = 'عذراً، ليس لديك الصلاحية لحذف السجلات';
|
$error = 'ليس لديك صلاحية الحذف.';
|
||||||
} else {
|
} else {
|
||||||
$id = $_GET['id'];
|
|
||||||
$stmt = db()->prepare("DELETE FROM inbound_mail WHERE id = ?");
|
$stmt = db()->prepare("DELETE FROM inbound_mail WHERE id = ?");
|
||||||
$stmt->execute([$id]);
|
$stmt->execute([$id]);
|
||||||
$_SESSION['success'] = 'تم حذف البريد بنجاح';
|
$success = 'تم حذف البريد الوارد بنجاح.';
|
||||||
redirect('inbound.php');
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get session messages
|
// Fetch stats
|
||||||
if (isset($_SESSION['success'])) {
|
$total_stmt = db()->query("SELECT COUNT(*) FROM inbound_mail");
|
||||||
$success = $_SESSION['success'];
|
$total_inbound = $total_stmt->fetchColumn();
|
||||||
unset($_SESSION['success']);
|
|
||||||
}
|
|
||||||
if (isset($_SESSION['error'])) {
|
|
||||||
$error = $_SESSION['error'];
|
|
||||||
unset($_SESSION['error']);
|
|
||||||
}
|
|
||||||
|
|
||||||
$search = $_GET['search'] ?? '';
|
$pending_stmt = db()->prepare("SELECT COUNT(*) FROM inbound_mail WHERE status_id IN (SELECT id FROM mailbox_statuses WHERE is_default = 1 OR name LIKE '%قيد%')");
|
||||||
$my_tasks = isset($_GET['my_tasks']) && $_GET['my_tasks'] == 1;
|
$pending_stmt->execute();
|
||||||
|
$pending_inbound = $pending_stmt->fetchColumn();
|
||||||
|
|
||||||
// Pagination settings
|
// Search and Filter
|
||||||
$limit = 10; // Items per page
|
$where = "WHERE 1=1";
|
||||||
$page = isset($_GET['page']) && is_numeric($_GET['page']) ? (int)$_GET['page'] : 1;
|
|
||||||
if ($page < 1) $page = 1;
|
|
||||||
$offset = ($page - 1) * $limit;
|
|
||||||
|
|
||||||
$where_clauses = ["1=1"];
|
|
||||||
$params = [];
|
$params = [];
|
||||||
|
|
||||||
if ($search) {
|
if (isset($_GET['search']) && !empty($_GET['search'])) {
|
||||||
$where_clauses[] = "(m.ref_no LIKE ? OR m.sender LIKE ? OR m.subject LIKE ?)";
|
$where .= " AND (m.ref_no LIKE ? OR m.subject LIKE ? OR m.sender LIKE ? OR m.recipient LIKE ?)";
|
||||||
$params[] = "%$search%";
|
$search = "%" . $_GET['search'] . "%";
|
||||||
$params[] = "%$search%";
|
$params = array_merge($params, [$search, $search, $search, $search]);
|
||||||
$params[] = "%$search%";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($my_tasks) {
|
if (isset($_GET['status_id']) && !empty($_GET['status_id'])) {
|
||||||
$where_clauses[] = "m.assigned_to = ?";
|
$where .= " AND m.status_id = ?";
|
||||||
$params[] = $user_id;
|
$params[] = $_GET['status_id'];
|
||||||
}
|
}
|
||||||
|
|
||||||
$where_sql = implode(" AND ", $where_clauses);
|
if (isset($_GET['my_tasks'])) {
|
||||||
|
$where .= " AND m.assigned_to = ?";
|
||||||
|
$params[] = $_SESSION['user_id'];
|
||||||
|
}
|
||||||
|
|
||||||
// Get total records for pagination
|
|
||||||
$count_query = "SELECT COUNT(*) FROM inbound_mail m WHERE $where_sql";
|
|
||||||
$stmt_count = db()->prepare($count_query);
|
|
||||||
$stmt_count->execute($params);
|
|
||||||
$total_records = $stmt_count->fetchColumn();
|
|
||||||
$total_pages = ceil($total_records / $limit);
|
|
||||||
|
|
||||||
// Fetch paginated results
|
|
||||||
$query = "SELECT m.*, s.name as status_name, s.color as status_color, u.full_name as assigned_to_name,
|
$query = "SELECT m.*, s.name as status_name, s.color as status_color, u.full_name as assigned_to_name,
|
||||||
(SELECT GROUP_CONCAT(display_name SEPARATOR '|||') FROM inbound_attachments WHERE mail_id = m.id) as attachment_names
|
(SELECT GROUP_CONCAT(display_name SEPARATOR '|||') FROM inbound_attachments WHERE mail_id = m.id) as attachment_names
|
||||||
FROM inbound_mail m
|
FROM inbound_mail m
|
||||||
LEFT JOIN mailbox_statuses s ON m.status_id = s.id
|
LEFT JOIN mailbox_statuses s ON m.status_id = s.id
|
||||||
LEFT JOIN users u ON m.assigned_to = u.id
|
LEFT JOIN users u ON m.assigned_to = u.id
|
||||||
WHERE $where_sql
|
$where
|
||||||
ORDER BY m.created_at DESC
|
ORDER BY m.date_registered DESC, m.id DESC";
|
||||||
LIMIT $limit OFFSET $offset";
|
|
||||||
|
|
||||||
$stmt = db()->prepare($query);
|
$stmt = db()->prepare($query);
|
||||||
$stmt->execute($params);
|
$stmt->execute($params);
|
||||||
$mails = $stmt->fetchAll();
|
$mails = $stmt->fetchAll();
|
||||||
|
|
||||||
$users_list = db()->query("SELECT id, full_name FROM users ORDER BY full_name")->fetchAll();
|
$statuses = db()->query("SELECT * FROM mailbox_statuses ORDER BY id ASC")->fetchAll();
|
||||||
|
$users = db()->query("SELECT id, full_name, username FROM users ORDER BY full_name ASC")->fetchAll();
|
||||||
|
$default_status_id = db()->query("SELECT id FROM mailbox_statuses WHERE is_default = 1 LIMIT 1")->fetchColumn() ?: ($statuses[0]['id'] ?? null);
|
||||||
|
|
||||||
// Handle Deep Link for Edit
|
|
||||||
$deepLinkData = null;
|
$deepLinkData = null;
|
||||||
if (isset($_GET['action']) && $_GET['action'] === 'edit' && isset($_GET['id'])) {
|
if (isset($_GET['id'])) {
|
||||||
if (canEdit('inbound')) {
|
$dlStmt = db()->prepare("SELECT m.*, (SELECT GROUP_CONCAT(display_name SEPARATOR '|||') FROM inbound_attachments WHERE mail_id = m.id) as attachment_names FROM inbound_mail m WHERE m.id = ?");
|
||||||
$stmt = db()->prepare("SELECT m.*, (SELECT GROUP_CONCAT(display_name SEPARATOR '|||') FROM inbound_attachments WHERE mail_id = m.id) as attachment_names FROM inbound_mail m WHERE m.id = ? ");
|
$dlStmt->execute([$_GET['id']]);
|
||||||
$stmt->execute([$_GET['id']]);
|
$deepLinkData = $dlStmt->fetch();
|
||||||
$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 '<span class="badge" style="background-color: ' . $status_color . ';">' . htmlspecialchars($display_name) . '</span>';
|
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
|
<div class="container-fluid py-4">
|
||||||
<h1 class="h2">البريد الوارد</h1>
|
<div class="row mb-4">
|
||||||
|
<div class="col-md-8">
|
||||||
|
<h2 class="fw-bold mb-1"><i class="fas fa-download text-primary me-2"></i> البريد الوارد</h2>
|
||||||
|
<p class="text-muted">إدارة جميع المراسلات الواردة والمهام المسندة.</p>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4 text-md-end d-flex align-items-center justify-content-md-end gap-2">
|
||||||
<?php if (canAdd('inbound')): ?>
|
<?php if (canAdd('inbound')): ?>
|
||||||
<button type="button" class="btn btn-primary shadow-sm" onclick="openMailModal('add')">
|
<button class="btn btn-primary px-4 py-2" onclick="openMailModal('add')">
|
||||||
<i class="fas fa-plus-circle me-1"></i> إضافة جديد
|
<i class="fas fa-plus me-1"></i> إضافة بريد جديد
|
||||||
</button>
|
</button>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<?php if ($success): ?>
|
|
||||||
<div class="alert alert-success alert-dismissible fade show" role="alert">
|
|
||||||
<?= $success ?>
|
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
|
||||||
</div>
|
</div>
|
||||||
<?php endif; ?>
|
|
||||||
|
<!-- Stats Cards -->
|
||||||
|
<div class="row g-3 mb-4">
|
||||||
|
<div class="col-md-3">
|
||||||
|
<div class="card border-0 shadow-sm h-100">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="d-flex align-items-center mb-3">
|
||||||
|
<div class="rounded-circle bg-primary bg-opacity-10 p-3 me-3">
|
||||||
|
<i class="fas fa-inbox text-primary fa-lg"></i>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h6 class="card-subtitle text-muted mb-1 small">إجمالي الوارد</h6>
|
||||||
|
<h3 class="card-title mb-0 fw-bold"><?= $total_inbound ?></h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3">
|
||||||
|
<div class="card border-0 shadow-sm h-100">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="d-flex align-items-center mb-3">
|
||||||
|
<div class="rounded-circle bg-warning bg-opacity-10 p-3 me-3">
|
||||||
|
<i class="fas fa-clock text-warning fa-lg"></i>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h6 class="card-subtitle text-muted mb-1 small">قيد المعالجة</h6>
|
||||||
|
<h3 class="card-title mb-0 fw-bold"><?= $pending_inbound ?></h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<?php if ($error): ?>
|
<?php if ($error): ?>
|
||||||
<div class="alert alert-danger alert-dismissible fade show" role="alert">
|
<div class="alert alert-danger shadow-sm border-0 mb-4"><?= $error ?></div>
|
||||||
<?= $error ?>
|
<?php endif; ?>
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
<?php if ($success): ?>
|
||||||
</div>
|
<div class="alert alert-success shadow-sm border-0 mb-4"><?= $success ?></div>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<div class="card shadow-sm border-0 mb-4">
|
<!-- Filter Bar -->
|
||||||
<div class="card-header bg-white py-3">
|
<div class="card border-0 shadow-sm mb-4">
|
||||||
<form class="row g-3 align-items-center">
|
<div class="card-body p-3">
|
||||||
|
<form method="GET" class="row g-2 align-items-center">
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<input type="text" name="search" class="form-control" placeholder="بحث برقم القيد أو الموضوع أو المرسل..." value="<?= htmlspecialchars($search) ?>">
|
<div class="input-group">
|
||||||
|
<span class="input-group-text bg-white border-end-0"><i class="fas fa-search text-muted"></i></span>
|
||||||
|
<input type="text" name="search" class="form-control border-start-0" placeholder="بحث برقم القيد، الموضوع، أو المرسل..." value="<?= htmlspecialchars($_GET['search'] ?? '') ?>">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3">
|
||||||
|
<select name="status_id" class="form-select" onchange="this.form.submit()">
|
||||||
|
<option value="">جميع الحالات</option>
|
||||||
|
<?php foreach ($statuses as $status): ?>
|
||||||
|
<option value="<?= $status['id'] ?>" <?= (isset($_GET['status_id']) && $_GET['status_id'] == $status['id']) ? 'selected' : '' ?>><?= $status['name'] ?></option>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-3">
|
<div class="col-md-3">
|
||||||
<div class="form-check form-switch mt-1">
|
<div class="form-check form-switch mt-1">
|
||||||
<input class="form-check-input" type="checkbox" name="my_tasks" id="myTasksSwitch" value="1" <?= $my_tasks ? 'checked' : '' ?> onchange="this.form.submit()">
|
<input class="form-check-input" type="checkbox" name="my_tasks" id="myTasks" <?= isset($_GET['my_tasks']) ? 'checked' : '' ?> onchange="this.form.submit()">
|
||||||
<label class="form-check-label fw-bold" for="myTasksSwitch">مهامي فقط</label>
|
<label class="form-check-label ms-2" for="myTasks">مهامي فقط</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-auto">
|
<div class="col-md-2 text-end">
|
||||||
<button type="submit" class="btn btn-secondary px-4">بحث</button>
|
<button type="submit" class="btn btn-light w-100">تصفية</button>
|
||||||
</div>
|
</div>
|
||||||
<?php if ($search || $my_tasks): ?>
|
|
||||||
<div class="col-auto">
|
|
||||||
<a href="inbound.php" class="btn btn-link text-decoration-none">إلغاء التصفية</a>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body p-0">
|
</div>
|
||||||
|
|
||||||
|
<!-- Mails Table -->
|
||||||
|
<div class="card border-0 shadow-sm overflow-hidden">
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table class="table table-hover align-middle mb-0">
|
<table class="table table-hover align-middle mb-0">
|
||||||
<thead class="bg-light">
|
<thead class="bg-light">
|
||||||
<tr>
|
<tr>
|
||||||
<th class="ps-4">رقم القيد</th>
|
<th class="ps-4">رقم القيد</th>
|
||||||
<th>التاريخ</th>
|
<th>التاريخ</th>
|
||||||
<th>الموعد النهائي</th>
|
|
||||||
<th>الموضوع</th>
|
<th>الموضوع</th>
|
||||||
<th>المرسل</th>
|
<th>الجهة المرسلة</th>
|
||||||
<th>المرفقات</th>
|
|
||||||
<th>المسؤول</th>
|
|
||||||
<th>الحالة</th>
|
<th>الحالة</th>
|
||||||
<th class="pe-4 text-center">الإجراءات</th>
|
<th>المسؤول</th>
|
||||||
|
<th class="text-center pe-4">الإجراءات</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<?php if ($mails): foreach ($mails as $mail): ?>
|
<?php if (empty($mails)): ?>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="ps-4 fw-bold text-primary"><?= $mail['ref_no'] ?></td>
|
<td colspan="7" class="text-center py-5 text-muted">
|
||||||
<td><?= $mail['date_registered'] ?></td>
|
<i class="fas fa-inbox fa-3x mb-3 opacity-20"></i>
|
||||||
<td>
|
<p>لا يوجد بريد وارد حالياً.</p>
|
||||||
<?php if ($mail['due_date']): ?>
|
</td>
|
||||||
<span class="<?= (strtotime($mail['due_date']) < time() && $mail['status_name'] != 'closed') ? 'text-danger fw-bold' : '' ?>">
|
</tr>
|
||||||
<?= $mail['due_date'] ?>
|
|
||||||
<?php if (strtotime($mail['due_date']) < time() && $mail['status_name'] != 'closed'): ?>
|
|
||||||
<i class="fas fa-exclamation-triangle ms-1"></i>
|
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
<?php foreach ($mails as $mail): ?>
|
||||||
|
<tr>
|
||||||
|
<td class="ps-4"><span class="fw-bold text-primary"><?= htmlspecialchars($mail['ref_no']) ?></span></td>
|
||||||
|
<td><?= date('Y-m-d', strtotime($mail['date_registered'])) ?></td>
|
||||||
|
<td>
|
||||||
|
<div class="fw-semibold text-truncate" style="max-width: 250px;"><?= htmlspecialchars($mail['subject']) ?></div>
|
||||||
|
<?php if ($mail['attachment_names']): ?>
|
||||||
|
<span class="badge bg-light text-muted fw-normal" style="font-size: 0.65rem;">
|
||||||
|
<i class="fas fa-paperclip me-1"></i> <?= count(explode('|||', $mail['attachment_names'])) ?> مرفقات
|
||||||
</span>
|
</span>
|
||||||
<?php else: ?>
|
|
||||||
<span class="text-muted">-</span>
|
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</td>
|
</td>
|
||||||
<td><?= htmlspecialchars($mail['subject']) ?></td>
|
|
||||||
<td><?= htmlspecialchars($mail['sender']) ?></td>
|
<td><?= htmlspecialchars($mail['sender']) ?></td>
|
||||||
<td>
|
<td>
|
||||||
<?php if (!empty($mail['attachment_names'])): ?>
|
<span class="badge rounded-pill" style="background-color: <?= $mail['status_color'] ?>20; color: <?= $mail['status_color'] ?>;">
|
||||||
<small class="text-muted"><i class="fas fa-paperclip me-1"></i> <?= htmlspecialchars(str_replace('|||', ', ', $mail['attachment_names'])) ?></small>
|
<i class="fas fa-circle me-1 small"></i> <?= htmlspecialchars($mail['status_name']) ?>
|
||||||
<?php else: ?>
|
</span>
|
||||||
<span class="text-muted">-</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<?php if ($mail['assigned_to_name']): ?>
|
<div class="d-flex align-items-center">
|
||||||
<span class="text-nowrap"><i class="fas fa-user-tag me-1 text-muted"></i> <?= htmlspecialchars($mail['assigned_to_name']) ?></span>
|
<div class="rounded-circle bg-light d-flex align-items-center justify-content-center me-2" style="width: 24px; height: 24px;">
|
||||||
<?php else: ?>
|
<i class="fas fa-user-circle text-muted small"></i>
|
||||||
<span class="text-muted">غير معين</span>
|
</div>
|
||||||
<?php endif; ?>
|
<span class="small"><?= htmlspecialchars($mail['assigned_to_name'] ?: 'غير محدد') ?></span>
|
||||||
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td><?= getStatusBadgeInList($mail) ?></td>
|
<td class="text-center pe-4">
|
||||||
<td class="pe-4 text-center">
|
<div class="btn-group shadow-sm rounded">
|
||||||
<a href="view_mail.php?id=<?= $mail['id'] ?>" class="btn btn-sm btn-outline-info" title="عرض التفاصيل"><i class="fas fa-eye"></i></a>
|
<a href="view_mail.php?id=<?= $mail['id'] ?>&type=inbound" class="btn btn-sm btn-white text-primary border" title="عرض">
|
||||||
|
<i class="fas fa-eye"></i>
|
||||||
|
</a>
|
||||||
<?php if (canEdit('inbound')): ?>
|
<?php if (canEdit('inbound')): ?>
|
||||||
<button type="button" class="btn btn-sm btn-outline-primary"
|
<button class="btn btn-sm btn-white text-warning border" onclick='openMailModal("edit", <?= json_encode($mail) ?>)' title="تعديل">
|
||||||
onclick='openMailModal("edit", <?= json_encode($mail) ?>)' title="تعديل">
|
|
||||||
<i class="fas fa-edit"></i>
|
<i class="fas fa-edit"></i>
|
||||||
</button>
|
</button>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<?php if (canDelete('inbound')): ?>
|
<?php if (canDelete('inbound')): ?>
|
||||||
<a href="javascript:void(0)" onclick="confirmDelete(<?= $mail['id'] ?>)" class="btn btn-sm btn-outline-danger" title="حذف"><i class="fas fa-trash"></i></a>
|
<form method="POST" class="d-inline" onsubmit="return confirm('هل أنت متأكد من حذف هذا البريد؟');">
|
||||||
|
<input type="hidden" name="action" value="delete">
|
||||||
|
<input type="hidden" name="id" value="<?= $mail['id'] ?>">
|
||||||
|
<button type="submit" class="btn btn-sm btn-white text-danger border rounded-0" title="حذف">
|
||||||
|
<i class="fas fa-trash"></i>
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<?php endforeach; else: ?>
|
<?php endforeach; ?>
|
||||||
<tr>
|
|
||||||
<td colspan="9" class="text-center py-4 text-muted">لا يوجد بريد وارد مسجل حالياً</td>
|
|
||||||
</tr>
|
|
||||||
<?php endif; ?>
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<?php if ($total_pages > 1): ?>
|
|
||||||
<div class="card-footer bg-white border-0 py-3">
|
|
||||||
<nav aria-label="Page navigation">
|
|
||||||
<ul class="pagination justify-content-center mb-0">
|
|
||||||
<li class="page-item <?= ($page <= 1) ? 'disabled' : '' ?>">
|
|
||||||
<a class="page-link" href="?page=<?= $page - 1 ?><?= $search ? '&search='.urlencode($search) : '' ?><?= $my_tasks ? '&my_tasks=1' : '' ?>" aria-label="Previous">
|
|
||||||
<span aria-hidden="true">«</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<?php for ($i = 1; $i <= $total_pages; $i++): ?>
|
|
||||||
<li class="page-item <?= ($page == $i) ? 'active' : '' ?>">
|
|
||||||
<a class="page-link" href="?page=<?= $i ?><?= $search ? '&search='.urlencode($search) : '' ?><?= $my_tasks ? '&my_tasks=1' : '' ?>"><?= $i ?></a>
|
|
||||||
</li>
|
|
||||||
<?php endfor; ?>
|
|
||||||
<li class="page-item <?= ($page >= $total_pages) ? 'disabled' : '' ?>">
|
|
||||||
<a class="page-link" href="?page=<?= $page + 1 ?><?= $search ? '&search='.urlencode($search) : '' ?><?= $my_tasks ? '&my_tasks=1' : '' ?>" aria-label="Next">
|
|
||||||
<span aria-hidden="true">»</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</nav>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<?php if (canAdd('inbound') || canEdit('inbound')): ?>
|
<!-- Add/Edit Modal -->
|
||||||
<!-- Mail Modal -->
|
|
||||||
<div class="modal fade" id="mailModal" tabindex="-1" aria-labelledby="mailModalLabel" aria-hidden="true">
|
<div class="modal fade" id="mailModal" tabindex="-1" aria-labelledby="mailModalLabel" aria-hidden="true">
|
||||||
<div class="modal-dialog modal-lg">
|
<div class="modal-dialog modal-lg">
|
||||||
<div class="modal-content border-0 shadow">
|
<div class="modal-content border-0 shadow">
|
||||||
<div class="modal-header bg-primary text-white">
|
<div class="modal-header bg-primary text-white py-3">
|
||||||
<h5 class="modal-title fw-bold" id="mailModalLabel">إضافة بريد وارد جديد</h5>
|
<h5 class="modal-title fw-bold" id="mailModalLabel">بريد وارد جديد</h5>
|
||||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
|
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
</div>
|
</div>
|
||||||
<form id="mailForm" method="POST" enctype="multipart/form-data">
|
<form id="mailForm" method="POST" enctype="multipart/form-data">
|
||||||
@ -394,66 +304,63 @@ function getStatusBadgeInList($mail) {
|
|||||||
<input type="hidden" name="id" id="modalId" value="0">
|
<input type="hidden" name="id" id="modalId" value="0">
|
||||||
|
|
||||||
<div class="row g-3">
|
<div class="row g-3">
|
||||||
<div class="col-md-4">
|
<div class="col-md-6">
|
||||||
<label class="form-label fw-bold">رقم القيد <span class="text-danger">*</span></label>
|
<label class="form-label small fw-bold">رقم القيد</label>
|
||||||
<input type="text" name="ref_no" id="modalRefNo" class="form-control" required readonly>
|
<input type="text" name="ref_no" id="modalRefNo" class="form-control" readonly required>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-4">
|
<div class="col-md-6">
|
||||||
<label class="form-label fw-bold">تاريخ التسجيل</label>
|
<label class="form-label small fw-bold">تاريخ التسجيل</label>
|
||||||
<input type="date" name="date_registered" id="modalDateRegistered" class="form-control">
|
<input type="date" name="date_registered" id="modalDateRegistered" class="form-control" required>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-4">
|
<div class="col-md-6">
|
||||||
<label class="form-label fw-bold">الموعد النهائي</label>
|
<label class="form-label small fw-bold">الجهة المرسلة</label>
|
||||||
|
<input type="text" name="sender" id="modalSender" class="form-control" required placeholder="مثال: وزارة العدل">
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label small fw-bold">الجهة المستلمة (الداخلية)</label>
|
||||||
|
<input type="text" name="recipient" id="modalRecipient" class="form-control" required placeholder="مثال: مكتب المدير العام">
|
||||||
|
</div>
|
||||||
|
<div class="col-md-12">
|
||||||
|
<label class="form-label small fw-bold">الموضوع</label>
|
||||||
|
<input type="text" name="subject" id="modalSubject" class="form-control" required>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-12">
|
||||||
|
<label class="form-label small fw-bold">الوصف والملاحظات</label>
|
||||||
|
<textarea name="description" id="modalDescription" class="form-control" rows="5"></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label small fw-bold">تاريخ الاستحقاق (اختياري)</label>
|
||||||
<input type="date" name="due_date" id="modalDueDate" class="form-control">
|
<input type="date" name="due_date" id="modalDueDate" class="form-control">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label class="form-label fw-bold">المرسل</label>
|
<label class="form-label small fw-bold">الحالة</label>
|
||||||
<input type="text" name="sender" id="modalSender" class="form-control">
|
<select name="status_id" id="modalStatusId" class="form-select" required>
|
||||||
</div>
|
<?php foreach ($statuses as $status): ?>
|
||||||
<div class="col-md-6">
|
<option value="<?= $status['id'] ?>"><?= $status['name'] ?></option>
|
||||||
<label class="form-label fw-bold">المستلم الداخلي (القسم/الموظف)</label>
|
|
||||||
<input type="text" name="recipient" id="modalRecipient" class="form-control">
|
|
||||||
</div>
|
|
||||||
<div class="col-12">
|
|
||||||
<label class="form-label fw-bold">الموضوع <span class="text-danger">*</span></label>
|
|
||||||
<input type="text" name="subject" id="modalSubject" class="form-control" required>
|
|
||||||
</div>
|
|
||||||
<div class="col-12">
|
|
||||||
<label class="form-label fw-bold">الوصف / ملاحظات</label>
|
|
||||||
<textarea name="description" id="modalDescription" class="form-control" rows="5"></textarea>
|
|
||||||
</div>
|
|
||||||
<div class="col-12">
|
|
||||||
<label class="form-label fw-bold">المرفقات</label>
|
|
||||||
<input type="file" name="attachments[]" class="form-control" multiple>
|
|
||||||
<div id="modalExistingAttachments" class="mt-2"></div>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-6">
|
|
||||||
<label class="form-label fw-bold">الحالة</label>
|
|
||||||
<select name="status_id" id="modalStatusId" class="form-select">
|
|
||||||
<?php foreach ($statuses_list as $s): ?>
|
|
||||||
<?php
|
|
||||||
$d_name = $s['name'];
|
|
||||||
if ($d_name == 'received') $d_name = 'تم الاستلام';
|
|
||||||
if ($d_name == 'in_progress') $d_name = 'قيد المعالجة';
|
|
||||||
if ($d_name == 'closed') $d_name = 'مكتمل / مغلق';
|
|
||||||
?>
|
|
||||||
<option value="<?= $s['id'] ?>"><?= htmlspecialchars($d_name) ?></option>
|
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-12">
|
||||||
<label class="form-label fw-bold">الموظف المسؤول</label>
|
<label class="form-label small fw-bold">إسناد المهمة إلى</label>
|
||||||
<select name="assigned_to" id="modalAssignedTo" class="form-select">
|
<select name="assigned_to" id="modalAssignedTo" class="form-select">
|
||||||
<option value="">-- اختر موظف --</option>
|
<option value="">--- اختر مستخدم ---</option>
|
||||||
<?php foreach ($users_list as $u): ?>
|
<?php foreach ($users as $user): ?>
|
||||||
<option value="<?= $u['id'] ?>"><?= htmlspecialchars($u['full_name']) ?></option>
|
<option value="<?= $user['id'] ?>"><?= htmlspecialchars($user['full_name'] ?: $user['username']) ?></option>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-md-12 mt-4">
|
||||||
|
<div class="bg-light p-3 rounded">
|
||||||
|
<label class="form-label small fw-bold mb-2 d-block">المرفقات</label>
|
||||||
|
<input type="file" name="attachments[]" id="modalAttachmentsInput" class="form-control" multiple>
|
||||||
|
<div id="modalExistingAttachments" class="mt-2"></div>
|
||||||
|
<div id="modalSelectedAttachments" class="mt-1"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer bg-light">
|
</div>
|
||||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">إلغاء</button>
|
</div>
|
||||||
|
<div class="modal-footer bg-light border-0">
|
||||||
|
<button type="button" class="btn btn-white border px-4" data-bs-dismiss="modal">إلغاء</button>
|
||||||
<button type="submit" class="btn btn-primary px-4">حفظ البيانات</button>
|
<button type="submit" class="btn btn-primary px-4">حفظ البيانات</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
@ -461,25 +368,52 @@ function getStatusBadgeInList($mail) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
/* Custom Table Styles */
|
||||||
|
.table thead th {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.05rem;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #6c757d;
|
||||||
|
border-top: none;
|
||||||
|
padding: 1rem 0.5rem;
|
||||||
|
}
|
||||||
|
.btn-white {
|
||||||
|
background-color: #fff;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
.btn-white:hover {
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
}
|
||||||
|
.badge {
|
||||||
|
padding: 0.5em 0.8em;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
.input-group-text {
|
||||||
|
color: #adb5bd;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
let descriptionEditor;
|
|
||||||
let mailModal;
|
let mailModal;
|
||||||
|
|
||||||
function initEditors() {
|
function initEditors() {
|
||||||
if (typeof ClassicEditor === 'undefined') {
|
if (typeof tinymce === 'undefined') {
|
||||||
console.error('CKEditor not loaded');
|
console.error('TinyMCE not loaded');
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
const config = {
|
return tinymce.init({
|
||||||
|
selector: '#modalDescription',
|
||||||
language: 'ar',
|
language: 'ar',
|
||||||
toolbar: ['heading', '|', 'bold', 'italic', 'link', 'bulletedList', 'numberedList', 'undo', 'redo']
|
directionality: 'rtl',
|
||||||
};
|
height: 300,
|
||||||
|
plugins: 'advlist autolink lists link image charmap preview anchor searchreplace visualblocks code fullscreen insertdatetime media table help wordcount',
|
||||||
return ClassicEditor.create(document.querySelector('#modalDescription'), config)
|
toolbar: 'undo redo | fontfamily fontsize | bold italic underline strikethrough | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | removeformat | help',
|
||||||
.then(editor => { descriptionEditor = editor; })
|
font_size_formats: '8pt 10pt 12pt 14pt 18pt 24pt 36pt',
|
||||||
.catch(err => {
|
promotion: false,
|
||||||
console.error('CKEditor Init Error:', err);
|
branding: false
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -498,6 +432,8 @@ function openMailModal(action, data = null) {
|
|||||||
const modalAction = document.getElementById('modalAction');
|
const modalAction = document.getElementById('modalAction');
|
||||||
const modalId = document.getElementById('modalId');
|
const modalId = document.getElementById('modalId');
|
||||||
const existingAttachmentsDiv = document.getElementById('modalExistingAttachments');
|
const existingAttachmentsDiv = document.getElementById('modalExistingAttachments');
|
||||||
|
const selectedAttachmentsDiv = document.getElementById('modalSelectedAttachments');
|
||||||
|
const attachmentsInput = document.getElementById('modalAttachmentsInput');
|
||||||
|
|
||||||
const fields = {
|
const fields = {
|
||||||
ref_no: document.getElementById('modalRefNo'),
|
ref_no: document.getElementById('modalRefNo'),
|
||||||
@ -512,6 +448,8 @@ function openMailModal(action, data = null) {
|
|||||||
|
|
||||||
modalAction.value = action;
|
modalAction.value = action;
|
||||||
existingAttachmentsDiv.innerHTML = '';
|
existingAttachmentsDiv.innerHTML = '';
|
||||||
|
selectedAttachmentsDiv.innerHTML = '';
|
||||||
|
if (attachmentsInput) attachmentsInput.value = '';
|
||||||
|
|
||||||
if (action === 'add') {
|
if (action === 'add') {
|
||||||
label.textContent = 'إضافة بريد وارد جديد';
|
label.textContent = 'إضافة بريد وارد جديد';
|
||||||
@ -525,8 +463,11 @@ function openMailModal(action, data = null) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (descriptionEditor) descriptionEditor.setData('');
|
if (typeof tinymce !== 'undefined' && tinymce.get('modalDescription')) {
|
||||||
else document.getElementById('modalDescription').value = '';
|
tinymce.get('modalDescription').setContent('');
|
||||||
|
} else {
|
||||||
|
document.getElementById('modalDescription').value = '';
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
label.textContent = 'تعديل البريد الوارد';
|
label.textContent = 'تعديل البريد الوارد';
|
||||||
modalId.value = data.id;
|
modalId.value = data.id;
|
||||||
@ -534,8 +475,11 @@ function openMailModal(action, data = null) {
|
|||||||
if (fields[key]) fields[key].value = data[key] || '';
|
if (fields[key]) fields[key].value = data[key] || '';
|
||||||
});
|
});
|
||||||
|
|
||||||
if (descriptionEditor) descriptionEditor.setData(data.description || '');
|
if (typeof tinymce !== 'undefined' && tinymce.get('modalDescription')) {
|
||||||
else document.getElementById('modalDescription').value = data.description || '';
|
tinymce.get('modalDescription').setContent(data.description || '');
|
||||||
|
} else {
|
||||||
|
document.getElementById('modalDescription').value = data.description || '';
|
||||||
|
}
|
||||||
|
|
||||||
// Display existing attachments
|
// Display existing attachments
|
||||||
if (data.attachment_names) {
|
if (data.attachment_names) {
|
||||||
@ -557,68 +501,37 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
<?php if ($deepLinkData): ?>
|
<?php if ($deepLinkData): ?>
|
||||||
openMailModal('edit', <?= json_encode($deepLinkData) ?>);
|
openMailModal('edit', <?= json_encode($deepLinkData) ?>);
|
||||||
<?php elseif ($error && isset($_POST['action'])): ?>
|
<?php elseif ($error && isset($_POST['action'])): ?>
|
||||||
const errorData = <?= json_encode([
|
const errorData = <?= json_encode($_POST) ?>;
|
||||||
'id' => $_POST['id'] ?? 0,
|
openMailModal(errorData.action, errorData);
|
||||||
'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_id' => $_POST['status_id'] ?? $default_status_id,
|
|
||||||
'assigned_to' => $_POST['assigned_to'] ?? '',
|
|
||||||
'attachment_names' => $_POST['attachment_names'] ?? ''
|
|
||||||
]) ?>;
|
|
||||||
openMailModal('<?= $_POST['action'] ?>', errorData);
|
|
||||||
<?php elseif (isset($_GET['action']) && $_GET['action'] === 'add'): ?>
|
|
||||||
openMailModal('add');
|
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Handle file selection display
|
||||||
|
const attachmentsInput = document.getElementById('modalAttachmentsInput');
|
||||||
|
if (attachmentsInput) {
|
||||||
|
attachmentsInput.addEventListener('change', function() {
|
||||||
|
const fileList = this.files;
|
||||||
|
const selectedAttachmentsDiv = document.getElementById('modalSelectedAttachments');
|
||||||
|
selectedAttachmentsDiv.innerHTML = '';
|
||||||
|
|
||||||
|
if (fileList.length > 0) {
|
||||||
|
let html = '<div class="mt-2"><p class="mb-1 fw-bold small text-primary">المرفقات المختارة للرفع:</p><ul class="list-unstyled small">';
|
||||||
|
for (let i = 0; i < fileList.length; i++) {
|
||||||
|
const fileSize = (fileList[i].size / 1024).toFixed(1);
|
||||||
|
html += `<li><i class="fas fa-file-upload me-1 text-primary"></i> ${fileList[i].name} <span class="text-muted">(${fileSize} KB)</span></li>`;
|
||||||
|
}
|
||||||
|
html += '</ul></div>';
|
||||||
|
selectedAttachmentsDiv.innerHTML = html;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
document.getElementById('mailForm').addEventListener('submit', function() {
|
document.getElementById('mailForm').addEventListener('submit', function() {
|
||||||
if (descriptionEditor) descriptionEditor.updateSourceElement();
|
if (typeof tinymce !== 'undefined') {
|
||||||
|
tinymce.triggerSave();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
function confirmDelete(id) {
|
|
||||||
if (typeof Swal === 'undefined') {
|
|
||||||
if (confirm('هل أنت متأكد من الحذف؟')) {
|
|
||||||
window.location.href = 'inbound.php?action=delete&id=' + id;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Swal.fire({
|
|
||||||
title: 'هل أنت متأكد؟',
|
|
||||||
text: "لا يمكن التراجع عن عملية الحذف!",
|
|
||||||
icon: 'warning',
|
|
||||||
showCancelButton: true,
|
|
||||||
confirmButtonColor: '#d33',
|
|
||||||
cancelButtonColor: '#3085d6',
|
|
||||||
confirmButtonText: 'نعم، احذف!',
|
|
||||||
cancelButtonText: 'إلغاء'
|
|
||||||
}).then((result) => {
|
|
||||||
if (result.isConfirmed) {
|
|
||||||
window.location.href = 'inbound.php?action=delete&id=' + id;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<style>
|
<?php require_once 'includes/footer.php'; ?>
|
||||||
.ck-editor__editable_inline {
|
|
||||||
min-height: 250px;
|
|
||||||
direction: rtl;
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
.modal-content {
|
|
||||||
border-radius: 15px;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
.modal-header.bg-primary {
|
|
||||||
background-color: #0d6efd !important;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<?php require_once __DIR__ . '/includes/footer.php'; ?>
|
|
||||||
@ -36,12 +36,16 @@
|
|||||||
.footer .border-start {
|
.footer .border-start {
|
||||||
border-color: rgba(0,0,0,0.1) !important;
|
border-color: rgba(0,0,0,0.1) !important;
|
||||||
}
|
}
|
||||||
|
/* TinyMCE Fixes for Bootstrap Modals */
|
||||||
|
.tox-tinymce-aux {
|
||||||
|
z-index: 9999 !important;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<!-- Bootstrap Bundle -->
|
<!-- Bootstrap Bundle -->
|
||||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
<!-- CKEditor -->
|
<!-- TinyMCE Rich Text Editor -->
|
||||||
<script src="https://cdn.ckeditor.com/ckeditor5/40.0.0/classic/ckeditor.js"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/tinymce/6.8.2/tinymce.min.js"></script>
|
||||||
<!-- SweetAlert2 -->
|
<!-- SweetAlert2 -->
|
||||||
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
||||||
<!-- Main App JS -->
|
<!-- Main App JS -->
|
||||||
|
|||||||
@ -305,7 +305,8 @@ function getStatusBadgeInternal($mail) {
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<label class="form-label fw-bold">المرفقات</label>
|
<label class="form-label fw-bold">المرفقات</label>
|
||||||
<input type="file" name="attachments[]" class="form-control border-2" multiple>
|
<input type="file" name="attachments[]" id="composeAttachmentsInput" class="form-control border-2" multiple>
|
||||||
|
<div id="composeSelectedAttachments" class="mt-2"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -319,30 +320,58 @@ function getStatusBadgeInternal($mail) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
let composeEditor;
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
if (typeof ClassicEditor !== 'undefined') {
|
if (typeof tinymce !== 'undefined') {
|
||||||
ClassicEditor
|
tinymce.init({
|
||||||
.create(document.querySelector('#composeEditor'), {
|
selector: '#composeEditor',
|
||||||
language: 'ar',
|
language: 'ar',
|
||||||
toolbar: ['heading', '|', 'bold', 'italic', 'link', 'bulletedList', 'numberedList', 'blockQuote', 'undo', 'redo'],
|
directionality: 'rtl',
|
||||||
direction: 'rtl'
|
height: 400,
|
||||||
})
|
plugins: 'advlist autolink lists link image charmap preview anchor searchreplace visualblocks code fullscreen insertdatetime media table help wordcount',
|
||||||
.then(editor => {
|
toolbar: 'undo redo | fontfamily fontsize | bold italic underline strikethrough | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | removeformat | help',
|
||||||
composeEditor = editor;
|
font_size_formats: '8pt 10pt 12pt 14pt 18pt 24pt 36pt',
|
||||||
// Force RTL style on editable area
|
promotion: false,
|
||||||
editor.ui.view.editable.element.style.direction = 'rtl';
|
branding: false
|
||||||
editor.ui.view.editable.element.style.textAlign = 'right';
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.error(error);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
document.getElementById('composeForm').addEventListener('submit', function() {
|
document.getElementById('composeForm').addEventListener('submit', function() {
|
||||||
if (composeEditor) composeEditor.updateSourceElement();
|
if (typeof tinymce !== 'undefined') {
|
||||||
|
tinymce.triggerSave();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Handle file selection display
|
||||||
|
const attachmentsInput = document.getElementById('composeAttachmentsInput');
|
||||||
|
if (attachmentsInput) {
|
||||||
|
attachmentsInput.addEventListener('change', function() {
|
||||||
|
const fileList = this.files;
|
||||||
|
const selectedAttachmentsDiv = document.getElementById('composeSelectedAttachments');
|
||||||
|
selectedAttachmentsDiv.innerHTML = '';
|
||||||
|
|
||||||
|
if (fileList.length > 0) {
|
||||||
|
let html = '<div class="mt-2"><p class="mb-1 fw-bold small text-primary">المرفقات المختارة للرفع:</p><ul class="list-unstyled small">';
|
||||||
|
for (let i = 0; i < fileList.length; i++) {
|
||||||
|
const fileSize = (fileList[i].size / 1024).toFixed(1);
|
||||||
|
html += `<li><i class="fas fa-file-upload me-1 text-primary"></i> ${fileList[i].name} <span class="text-muted">(${fileSize} KB)</span></li>`;
|
||||||
|
}
|
||||||
|
html += '</ul></div>';
|
||||||
|
selectedAttachmentsDiv.innerHTML = html;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset attachments list when modal is hidden
|
||||||
|
const composeModal = document.getElementById('composeModal');
|
||||||
|
if (composeModal) {
|
||||||
|
composeModal.addEventListener('hidden.bs.modal', function () {
|
||||||
|
const selectedAttachmentsDiv = document.getElementById('composeSelectedAttachments');
|
||||||
|
const attachmentsInput = document.getElementById('composeAttachmentsInput');
|
||||||
|
if (selectedAttachmentsDiv) selectedAttachmentsDiv.innerHTML = '';
|
||||||
|
if (attachmentsInput) attachmentsInput.value = '';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
<?php if (isset($_GET['action']) && $_GET['action'] === 'compose'): ?>
|
<?php if (isset($_GET['action']) && $_GET['action'] === 'compose'): ?>
|
||||||
var myModal = new bootstrap.Modal(document.getElementById('composeModal'));
|
var myModal = new bootstrap.Modal(document.getElementById('composeModal'));
|
||||||
myModal.show();
|
myModal.show();
|
||||||
|
|||||||
683
outbound.php
683
outbound.php
@ -1,404 +1,284 @@
|
|||||||
<?php
|
<?php
|
||||||
require_once __DIR__ . '/includes/header.php';
|
require_once 'includes/header.php';
|
||||||
require_once __DIR__ . '/m_services/MailService.php';
|
|
||||||
|
|
||||||
// Check if user has view permission
|
|
||||||
if (!canView('outbound')) {
|
|
||||||
redirect('index.php');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Safe truncation helper
|
|
||||||
if (!function_exists('truncate_text')) {
|
|
||||||
function truncate_text($text, $limit = 100) {
|
|
||||||
$text = strip_tags($text);
|
|
||||||
if (function_exists('mb_strimwidth')) {
|
|
||||||
return mb_strimwidth($text, 0, $limit, "...");
|
|
||||||
}
|
|
||||||
if (strlen($text) <= $limit) return $text;
|
|
||||||
return substr($text, 0, $limit) . "...";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$error = '';
|
$error = '';
|
||||||
$success = '';
|
$success = '';
|
||||||
$user_id = $_SESSION['user_id'];
|
|
||||||
|
|
||||||
// Fetch statuses
|
// Handle CRUD operations
|
||||||
$statuses_list = db()->query("SELECT * FROM mailbox_statuses ORDER BY id ASC")->fetchAll();
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
|
||||||
$default_status_id = db()->query("SELECT id FROM mailbox_statuses WHERE is_default = 1 LIMIT 1")->fetchColumn() ?: 1;
|
if (!canEdit('outbound') && !canAdd('outbound')) {
|
||||||
|
$error = 'ليس لديك صلاحية للقيام بهذا الإجراء.';
|
||||||
// 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 = "
|
|
||||||
<div dir='rtl' style='font-family: Arial, sans-serif;'>
|
|
||||||
<h2>مرحباً " . htmlspecialchars($user['full_name']) . "</h2>
|
|
||||||
<p>لقد تم تعيين مهمة بريد جديد لك في النظام.</p>
|
|
||||||
<table border='1' cellpadding='10' cellspacing='0' style='border-collapse: collapse;'>
|
|
||||||
<tr>
|
|
||||||
<th style='background-color: #f8f9fa;'>رقم القيد</th>
|
|
||||||
<td>" . htmlspecialchars($ref_no) . "</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th style='background-color: #f8f9fa;'>الموضوع</th>
|
|
||||||
<td>" . htmlspecialchars($subject) . "</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<p>يرجى الدخول للنظام لمتابعة المهمة.</p>
|
|
||||||
<br>
|
|
||||||
<p>هذا تنبيه تلقائي، يرجى عدم الرد.</p>
|
|
||||||
</div>
|
|
||||||
";
|
|
||||||
MailService::sendMail($to, $email_subject, $htmlBody);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle actions
|
|
||||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
||||||
$action = $_POST['action'] ?? '';
|
|
||||||
|
|
||||||
// Permission checks for POST actions
|
|
||||||
if (($action === 'add' && !canAdd('outbound')) || ($action === 'edit' && !canEdit('outbound'))) {
|
|
||||||
$error = 'عذراً، ليس لديك الصلاحية للقيام بهذا الإجراء';
|
|
||||||
} else {
|
} else {
|
||||||
$type = 'outbound';
|
$action = $_POST['action'];
|
||||||
|
$id = $_POST['id'] ?? 0;
|
||||||
$ref_no = $_POST['ref_no'] ?? '';
|
$ref_no = $_POST['ref_no'] ?? '';
|
||||||
$date_registered = $_POST['date_registered'] ?? date('Y-m-d');
|
$date_registered = $_POST['date_registered'] ?? date('Y-m-d');
|
||||||
$due_date = !empty($_POST['due_date']) ? $_POST['due_date'] : null;
|
$due_date = $_POST['due_date'] ?? null;
|
||||||
$sender = $_POST['sender'] ?? '';
|
$sender = $_POST['sender'] ?? '';
|
||||||
$recipient = $_POST['recipient'] ?? '';
|
$recipient = $_POST['recipient'] ?? '';
|
||||||
$subject = $_POST['subject'] ?? '';
|
$subject = $_POST['subject'] ?? '';
|
||||||
$description = $_POST['description'] ?? '';
|
$description = $_POST['description'] ?? '';
|
||||||
$status_id = $_POST['status_id'] ?? $default_status_id;
|
$status_id = $_POST['status_id'] ?? null;
|
||||||
$assigned_to = !empty($_POST['assigned_to']) ? $_POST['assigned_to'] : null;
|
$assigned_to = $_POST['assigned_to'] ?? null;
|
||||||
$id = $_POST['id'] ?? 0;
|
|
||||||
|
|
||||||
if ($ref_no && $subject) {
|
if ($action === 'add' || $action === 'edit') {
|
||||||
$should_notify = false;
|
|
||||||
try {
|
try {
|
||||||
db()->beginTransaction();
|
db()->beginTransaction();
|
||||||
|
|
||||||
if ($action === 'add') {
|
if ($action === 'add') {
|
||||||
|
if (!canAdd('outbound')) throw new Exception('ليس لديك صلاحية الإضافة.');
|
||||||
$stmt = db()->prepare("INSERT INTO outbound_mail (ref_no, date_registered, due_date, sender, recipient, subject, description, status_id, assigned_to, created_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
$stmt = db()->prepare("INSERT INTO outbound_mail (ref_no, date_registered, due_date, sender, recipient, subject, description, status_id, assigned_to, created_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
||||||
$stmt->execute([$ref_no, $date_registered, $due_date, $sender, $recipient, $subject, $description, $status_id, $assigned_to, $user_id]);
|
$stmt->execute([$ref_no, $date_registered, $due_date, $sender, $recipient, $subject, $description, $status_id, $assigned_to, $_SESSION['user_id']]);
|
||||||
$mail_id = db()->lastInsertId();
|
$id = db()->lastInsertId();
|
||||||
|
$success = 'تم إضافة البريد الصادر بنجاح.';
|
||||||
if ($assigned_to) {
|
} else {
|
||||||
$should_notify = true;
|
if (!canEdit('outbound')) throw new Exception('ليس لديك صلاحية التعديل.');
|
||||||
}
|
|
||||||
|
|
||||||
$_SESSION['success'] = 'تمت إضافة البريد الصادر بنجاح';
|
|
||||||
} elseif ($action === 'edit') {
|
|
||||||
$mail_id = $id;
|
|
||||||
|
|
||||||
// Get previous assigned_to to check if it changed
|
|
||||||
$stmt_old = db()->prepare("SELECT assigned_to FROM outbound_mail WHERE id = ?");
|
|
||||||
$stmt_old->execute([$id]);
|
|
||||||
$old_assigned_to = $stmt_old->fetchColumn();
|
|
||||||
|
|
||||||
$stmt = db()->prepare("UPDATE outbound_mail SET ref_no = ?, date_registered = ?, due_date = ?, sender = ?, recipient = ?, subject = ?, description = ?, status_id = ?, assigned_to = ? WHERE id = ?");
|
$stmt = db()->prepare("UPDATE outbound_mail SET ref_no = ?, date_registered = ?, due_date = ?, sender = ?, recipient = ?, subject = ?, description = ?, status_id = ?, assigned_to = ? WHERE id = ?");
|
||||||
$stmt->execute([$ref_no, $date_registered, $due_date, $sender, $recipient, $subject, $description, $status_id, $assigned_to, $mail_id]);
|
$stmt->execute([$ref_no, $date_registered, $due_date, $sender, $recipient, $subject, $description, $status_id, $assigned_to, $id]);
|
||||||
|
$success = 'تم تحديث بيانات البريد الصادر بنجاح.';
|
||||||
if ($assigned_to && $assigned_to != $old_assigned_to) {
|
|
||||||
$should_notify = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$_SESSION['success'] = 'تم تحديث البيانات بنجاح';
|
// Handle file uploads
|
||||||
}
|
if (isset($_FILES['attachments']) && !empty($_FILES['attachments']['name'][0])) {
|
||||||
|
|
||||||
// Handle Attachments
|
|
||||||
if (!empty($_FILES['attachments']['name'][0])) {
|
|
||||||
$upload_dir = 'uploads/attachments/';
|
$upload_dir = 'uploads/attachments/';
|
||||||
if (!is_dir($upload_dir)) mkdir($upload_dir, 0777, true);
|
if (!is_dir($upload_dir)) mkdir($upload_dir, 0777, true);
|
||||||
|
|
||||||
foreach ($_FILES['attachments']['name'] as $key => $name) {
|
for ($i = 0; $i < count($_FILES['attachments']['name']); $i++) {
|
||||||
if ($_FILES['attachments']['error'][$key] === 0) {
|
if ($_FILES['attachments']['error'][$i] === 0) {
|
||||||
$file_name = time() . '_' . basename($name);
|
$filename = time() . '_' . $_FILES['attachments']['name'][$i];
|
||||||
$target_path = $upload_dir . $file_name;
|
$filepath = $upload_dir . $filename;
|
||||||
if (move_uploaded_file($_FILES['attachments']['tmp_name'][$key], $target_path)) {
|
if (move_uploaded_file($_FILES['attachments']['tmp_name'][$i], $filepath)) {
|
||||||
$stmt = db()->prepare("INSERT INTO outbound_attachments (mail_id, display_name, file_path, file_name, file_size) VALUES (?, ?, ?, ?, ?)");
|
$stmt = db()->prepare("INSERT INTO outbound_attachments (mail_id, display_name, file_path, file_name, file_size) VALUES (?, ?, ?, ?, ?)");
|
||||||
$stmt->execute([$mail_id, $name, $target_path, $name, $_FILES['attachments']['size'][$key]]);
|
$stmt->execute([$id, $_FILES['attachments']['name'][$i], $filepath, $_FILES['attachments']['name'][$i], $_FILES['attachments']['size'][$i]]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
db()->commit();
|
db()->commit();
|
||||||
|
} catch (Exception $e) {
|
||||||
// Notify after commit
|
db()->rollBack();
|
||||||
if ($should_notify) {
|
$error = 'خطأ: ' . $e->getMessage();
|
||||||
sendAssignmentNotification($assigned_to, $ref_no, $subject);
|
|
||||||
}
|
}
|
||||||
|
} elseif ($action === 'delete') {
|
||||||
redirect('outbound.php');
|
|
||||||
} catch (PDOException $e) {
|
|
||||||
if (db()->inTransaction()) db()->rollBack();
|
|
||||||
if ($e->getCode() == 23000) {
|
|
||||||
$error = 'رقم القيد مستخدم مسبقاً';
|
|
||||||
} else {
|
|
||||||
$error = 'حدث خطأ: ' . $e->getMessage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$error = 'يرجى ملء الحقول المطلوبة (رقم القيد، الموضوع)';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete action
|
|
||||||
if (isset($_GET['action']) && $_GET['action'] === 'delete' && isset($_GET['id'])) {
|
|
||||||
if (!canDelete('outbound')) {
|
if (!canDelete('outbound')) {
|
||||||
$error = 'عذراً، ليس لديك الصلاحية لحذف السجلات';
|
$error = 'ليس لديك صلاحية الحذف.';
|
||||||
} else {
|
} else {
|
||||||
$id = $_GET['id'];
|
|
||||||
$stmt = db()->prepare("DELETE FROM outbound_mail WHERE id = ?");
|
$stmt = db()->prepare("DELETE FROM outbound_mail WHERE id = ?");
|
||||||
$stmt->execute([$id]);
|
$stmt->execute([$id]);
|
||||||
$_SESSION['success'] = 'تم حذف البريد بنجاح';
|
$success = 'تم حذف البريد الصادر بنجاح.';
|
||||||
redirect('outbound.php');
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get session messages
|
// Fetch stats
|
||||||
if (isset($_SESSION['success'])) {
|
$total_stmt = db()->query("SELECT COUNT(*) FROM outbound_mail");
|
||||||
$success = $_SESSION['success'];
|
$total_outbound = $total_stmt->fetchColumn();
|
||||||
unset($_SESSION['success']);
|
|
||||||
}
|
|
||||||
if (isset($_SESSION['error'])) {
|
|
||||||
$error = $_SESSION['error'];
|
|
||||||
unset($_SESSION['error']);
|
|
||||||
}
|
|
||||||
|
|
||||||
$search = $_GET['search'] ?? '';
|
$completed_stmt = db()->prepare("SELECT COUNT(*) FROM outbound_mail WHERE status_id IN (SELECT id FROM mailbox_statuses WHERE name LIKE '%مكتمل%' OR name LIKE '%منتهي%')");
|
||||||
$my_tasks = isset($_GET['my_tasks']) && $_GET['my_tasks'] == 1;
|
$completed_stmt->execute();
|
||||||
|
$completed_outbound = $completed_stmt->fetchColumn();
|
||||||
|
|
||||||
// Pagination settings
|
// Search and Filter
|
||||||
$limit = 10; // Items per page
|
$where = "WHERE 1=1";
|
||||||
$page = isset($_GET['page']) && is_numeric($_GET['page']) ? (int)$_GET['page'] : 1;
|
|
||||||
if ($page < 1) $page = 1;
|
|
||||||
$offset = ($page - 1) * $limit;
|
|
||||||
|
|
||||||
$where_clauses = ["1=1"];
|
|
||||||
$params = [];
|
$params = [];
|
||||||
|
|
||||||
if ($search) {
|
if (isset($_GET['search']) && !empty($_GET['search'])) {
|
||||||
$where_clauses[] = "(m.ref_no LIKE ? OR m.recipient LIKE ? OR m.subject LIKE ?)";
|
$where .= " AND (m.ref_no LIKE ? OR m.subject LIKE ? OR m.sender LIKE ? OR m.recipient LIKE ?)";
|
||||||
$params[] = "%$search%";
|
$search = "%" . $_GET['search'] . "%";
|
||||||
$params[] = "%$search%";
|
$params = array_merge($params, [$search, $search, $search, $search]);
|
||||||
$params[] = "%$search%";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($my_tasks) {
|
if (isset($_GET['status_id']) && !empty($_GET['status_id'])) {
|
||||||
$where_clauses[] = "m.assigned_to = ?";
|
$where .= " AND m.status_id = ?";
|
||||||
$params[] = $user_id;
|
$params[] = $_GET['status_id'];
|
||||||
}
|
}
|
||||||
|
|
||||||
$where_sql = implode(" AND ", $where_clauses);
|
|
||||||
|
|
||||||
// Get total records for pagination
|
|
||||||
$count_query = "SELECT COUNT(*) FROM outbound_mail m WHERE $where_sql";
|
|
||||||
$stmt_count = db()->prepare($count_query);
|
|
||||||
$stmt_count->execute($params);
|
|
||||||
$total_records = $stmt_count->fetchColumn();
|
|
||||||
$total_pages = ceil($total_records / $limit);
|
|
||||||
|
|
||||||
// Fetch paginated results
|
|
||||||
$query = "SELECT m.*, s.name as status_name, s.color as status_color, u.full_name as assigned_to_name,
|
$query = "SELECT m.*, s.name as status_name, s.color as status_color, u.full_name as assigned_to_name,
|
||||||
(SELECT GROUP_CONCAT(display_name SEPARATOR '|||') FROM outbound_attachments WHERE mail_id = m.id) as attachment_names
|
(SELECT GROUP_CONCAT(display_name SEPARATOR '|||') FROM outbound_attachments WHERE mail_id = m.id) as attachment_names
|
||||||
FROM outbound_mail m
|
FROM outbound_mail m
|
||||||
LEFT JOIN mailbox_statuses s ON m.status_id = s.id
|
LEFT JOIN mailbox_statuses s ON m.status_id = s.id
|
||||||
LEFT JOIN users u ON m.assigned_to = u.id
|
LEFT JOIN users u ON m.assigned_to = u.id
|
||||||
WHERE $where_sql
|
$where
|
||||||
ORDER BY m.created_at DESC
|
ORDER BY m.date_registered DESC, m.id DESC";
|
||||||
LIMIT $limit OFFSET $offset";
|
|
||||||
|
|
||||||
$stmt = db()->prepare($query);
|
$stmt = db()->prepare($query);
|
||||||
$stmt->execute($params);
|
$stmt->execute($params);
|
||||||
$mails = $stmt->fetchAll();
|
$mails = $stmt->fetchAll();
|
||||||
|
|
||||||
$users_list = db()->query("SELECT id, full_name FROM users ORDER BY full_name")->fetchAll();
|
$statuses = db()->query("SELECT * FROM mailbox_statuses ORDER BY id ASC")->fetchAll();
|
||||||
|
$users = db()->query("SELECT id, full_name, username FROM users ORDER BY full_name ASC")->fetchAll();
|
||||||
|
$default_status_id = db()->query("SELECT id FROM mailbox_statuses WHERE is_default = 1 LIMIT 1")->fetchColumn() ?: ($statuses[0]['id'] ?? null);
|
||||||
|
|
||||||
// Handle Deep Link for Edit
|
|
||||||
$deepLinkData = null;
|
$deepLinkData = null;
|
||||||
if (isset($_GET['action']) && $_GET['action'] === 'edit' && isset($_GET['id'])) {
|
if (isset($_GET['id'])) {
|
||||||
if (canEdit('outbound')) {
|
$dlStmt = db()->prepare("SELECT m.*, (SELECT GROUP_CONCAT(display_name SEPARATOR '|||') FROM outbound_attachments WHERE mail_id = m.id) as attachment_names FROM outbound_mail m WHERE m.id = ?");
|
||||||
$stmt = db()->prepare("SELECT m.*, (SELECT GROUP_CONCAT(display_name SEPARATOR '|||') FROM outbound_attachments WHERE mail_id = m.id) as attachment_names FROM outbound_mail m WHERE m.id = ? ");
|
$dlStmt->execute([$_GET['id']]);
|
||||||
$stmt->execute([$_GET['id']]);
|
$deepLinkData = $dlStmt->fetch();
|
||||||
$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 '<span class="badge" style="background-color: ' . $status_color . ';">' . htmlspecialchars($display_name) . '</span>';
|
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
|
<div class="container-fluid py-4">
|
||||||
<h1 class="h2">البريد الصادر</h1>
|
<div class="row mb-4">
|
||||||
|
<div class="col-md-8">
|
||||||
|
<h2 class="fw-bold mb-1"><i class="fas fa-upload text-primary me-2"></i> البريد الصادر</h2>
|
||||||
|
<p class="text-muted">إدارة المراسلات الصادرة إلى الجهات الخارجية وتتبع حالاتها.</p>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4 text-md-end d-flex align-items-center justify-content-md-end gap-2">
|
||||||
<?php if (canAdd('outbound')): ?>
|
<?php if (canAdd('outbound')): ?>
|
||||||
<button type="button" class="btn btn-primary shadow-sm" onclick="openMailModal('add')">
|
<button class="btn btn-primary px-4 py-2" onclick="openMailModal('add')">
|
||||||
<i class="fas fa-plus-circle me-1"></i> إضافة جديد
|
<i class="fas fa-plus me-1"></i> إضافة صادر جديد
|
||||||
</button>
|
</button>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<?php if ($success): ?>
|
|
||||||
<div class="alert alert-success alert-dismissible fade show" role="alert">
|
|
||||||
<?= $success ?>
|
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
|
||||||
</div>
|
</div>
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<?php if ($error): ?>
|
<!-- Stats Cards -->
|
||||||
<div class="alert alert-danger alert-dismissible fade show" role="alert">
|
<div class="row g-3 mb-4">
|
||||||
<?= $error ?>
|
<div class="col-md-3">
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
<div class="card border-0 shadow-sm h-100">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="d-flex align-items-center mb-3">
|
||||||
|
<div class="rounded-circle bg-primary bg-opacity-10 p-3 me-3">
|
||||||
|
<i class="fas fa-paper-plane text-primary fa-lg"></i>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h6 class="card-subtitle text-muted mb-1 small">إجمالي الصادر</h6>
|
||||||
|
<h3 class="card-title mb-0 fw-bold"><?= $total_outbound ?></h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<div class="card shadow-sm border-0 mb-4">
|
|
||||||
<div class="card-header bg-white py-3">
|
|
||||||
<form class="row g-3 align-items-center">
|
|
||||||
<div class="col-md-4">
|
|
||||||
<input type="text" name="search" class="form-control" placeholder="بحث برقم القيد أو الموضوع أو المستلم..." value="<?= htmlspecialchars($search) ?>">
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-3">
|
<div class="col-md-3">
|
||||||
<div class="form-check form-switch mt-1">
|
<div class="card border-0 shadow-sm h-100">
|
||||||
<input class="form-check-input" type="checkbox" name="my_tasks" id="myTasksSwitch" value="1" <?= $my_tasks ? 'checked' : '' ?> onchange="this.form.submit()">
|
<div class="card-body">
|
||||||
<label class="form-check-label fw-bold" for="myTasksSwitch">مهامي فقط</label>
|
<div class="d-flex align-items-center mb-3">
|
||||||
|
<div class="rounded-circle bg-success bg-opacity-10 p-3 me-3">
|
||||||
|
<i class="fas fa-check-circle text-success fa-lg"></i>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h6 class="card-subtitle text-muted mb-1 small">مكتمل / مرسل</h6>
|
||||||
|
<h3 class="card-title mb-0 fw-bold"><?= $completed_outbound ?></h3>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-auto">
|
|
||||||
<button type="submit" class="btn btn-secondary px-4">بحث</button>
|
|
||||||
</div>
|
</div>
|
||||||
<?php if ($search || $my_tasks): ?>
|
|
||||||
<div class="col-auto">
|
|
||||||
<a href="outbound.php" class="btn btn-link text-decoration-none">إلغاء التصفية</a>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php if ($error): ?>
|
||||||
|
<div class="alert alert-danger shadow-sm border-0 mb-4"><?= $error ?></div>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
<?php if ($success): ?>
|
||||||
|
<div class="alert alert-success shadow-sm border-0 mb-4"><?= $success ?></div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<!-- Filter Bar -->
|
||||||
|
<div class="card border-0 shadow-sm mb-4">
|
||||||
|
<div class="card-body p-3">
|
||||||
|
<form method="GET" class="row g-2 align-items-center">
|
||||||
|
<div class="col-md-5">
|
||||||
|
<div class="input-group">
|
||||||
|
<span class="input-group-text bg-white border-end-0"><i class="fas fa-search text-muted"></i></span>
|
||||||
|
<input type="text" name="search" class="form-control border-start-0" placeholder="بحث برقم القيد، الموضوع، أو الجهة..." value="<?= htmlspecialchars($_GET['search'] ?? '') ?>">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<select name="status_id" class="form-select" onchange="this.form.submit()">
|
||||||
|
<option value="">جميع الحالات</option>
|
||||||
|
<?php foreach ($statuses as $status): ?>
|
||||||
|
<option value="<?= $status['id'] ?>" <?= (isset($_GET['status_id']) && $_GET['status_id'] == $status['id']) ? 'selected' : '' ?>><?= $status['name'] ?></option>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3 text-end">
|
||||||
|
<button type="submit" class="btn btn-light w-100">تصفية</button>
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body p-0">
|
</div>
|
||||||
|
|
||||||
|
<!-- Mails Table -->
|
||||||
|
<div class="card border-0 shadow-sm overflow-hidden">
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table class="table table-hover align-middle mb-0">
|
<table class="table table-hover align-middle mb-0">
|
||||||
<thead class="bg-light">
|
<thead class="bg-light">
|
||||||
<tr>
|
<tr>
|
||||||
<th class="ps-4">رقم القيد</th>
|
<th class="ps-4">رقم القيد</th>
|
||||||
<th>التاريخ</th>
|
<th>التاريخ</th>
|
||||||
<th>الموعد النهائي</th>
|
|
||||||
<th>الموضوع</th>
|
<th>الموضوع</th>
|
||||||
<th>المستلم</th>
|
<th>الجهة المستلمة</th>
|
||||||
<th>المرفقات</th>
|
|
||||||
<th>المسؤول</th>
|
|
||||||
<th>الحالة</th>
|
<th>الحالة</th>
|
||||||
<th class="pe-4 text-center">الإجراءات</th>
|
<th class="text-center pe-4">الإجراءات</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<?php if ($mails): foreach ($mails as $mail): ?>
|
<?php if (empty($mails)): ?>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="ps-4 fw-bold text-primary"><?= $mail['ref_no'] ?></td>
|
<td colspan="6" class="text-center py-5 text-muted">
|
||||||
<td><?= $mail['date_registered'] ?></td>
|
<i class="fas fa-paper-plane fa-3x mb-3 opacity-20"></i>
|
||||||
<td>
|
<p>لا يوجد بريد صادر حالياً.</p>
|
||||||
<?php if ($mail['due_date']): ?>
|
</td>
|
||||||
<span class="<?= (strtotime($mail['due_date']) < time() && $mail['status_name'] != 'closed') ? 'text-danger fw-bold' : '' ?>">
|
</tr>
|
||||||
<?= $mail['due_date'] ?>
|
|
||||||
<?php if (strtotime($mail['due_date']) < time() && $mail['status_name'] != 'closed'): ?>
|
|
||||||
<i class="fas fa-exclamation-triangle ms-1"></i>
|
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
<?php foreach ($mails as $mail): ?>
|
||||||
|
<tr>
|
||||||
|
<td class="ps-4"><span class="fw-bold text-primary"><?= htmlspecialchars($mail['ref_no']) ?></span></td>
|
||||||
|
<td><?= date('Y-m-d', strtotime($mail['date_registered'])) ?></td>
|
||||||
|
<td>
|
||||||
|
<div class="fw-semibold text-truncate" style="max-width: 300px;"><?= htmlspecialchars($mail['subject']) ?></div>
|
||||||
|
<?php if ($mail['attachment_names']): ?>
|
||||||
|
<span class="badge bg-light text-muted fw-normal" style="font-size: 0.65rem;">
|
||||||
|
<i class="fas fa-paperclip me-1"></i> <?= count(explode('|||', $mail['attachment_names'])) ?> مرفقات
|
||||||
</span>
|
</span>
|
||||||
<?php else: ?>
|
|
||||||
<span class="text-muted">-</span>
|
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</td>
|
</td>
|
||||||
<td><?= truncate_text($mail['subject'], 80) ?></td>
|
|
||||||
<td><?= htmlspecialchars($mail['recipient']) ?></td>
|
<td><?= htmlspecialchars($mail['recipient']) ?></td>
|
||||||
<td>
|
<td>
|
||||||
<?php if (!empty($mail['attachment_names'])): ?>
|
<span class="badge rounded-pill" style="background-color: <?= $mail['status_color'] ?>20; color: <?= $mail['status_color'] ?>;">
|
||||||
<small class="text-muted"><i class="fas fa-paperclip me-1"></i> <?= htmlspecialchars(str_replace('|||', ', ', $mail['attachment_names'])) ?></small>
|
<i class="fas fa-circle me-1 small"></i> <?= htmlspecialchars($mail['status_name']) ?>
|
||||||
<?php else: ?>
|
</span>
|
||||||
<span class="text-muted">-</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td class="text-center pe-4">
|
||||||
<?php if ($mail['assigned_to_name']): ?>
|
<div class="btn-group shadow-sm rounded">
|
||||||
<span class="text-nowrap"><i class="fas fa-user-tag me-1 text-muted"></i> <?= htmlspecialchars($mail['assigned_to_name']) ?></span>
|
<a href="view_mail.php?id=<?= $mail['id'] ?>&type=outbound" class="btn btn-sm btn-white text-primary border" title="عرض">
|
||||||
<?php else: ?>
|
<i class="fas fa-eye"></i>
|
||||||
<span class="text-muted">غير معين</span>
|
</a>
|
||||||
<?php endif; ?>
|
<a href="print_outbound.php?id=<?= $mail['id'] ?>" target="_blank" class="btn btn-sm btn-white text-secondary border" title="طباعة">
|
||||||
</td>
|
<i class="fas fa-print"></i>
|
||||||
<td><?= getStatusBadgeInList($mail) ?></td>
|
</a>
|
||||||
<td class="pe-4 text-center">
|
|
||||||
<a href="view_mail.php?id=<?= $mail['id'] ?>" class="btn btn-sm btn-outline-info" title="عرض التفاصيل"><i class="fas fa-eye"></i></a>
|
|
||||||
|
|
||||||
<?php if (canEdit('outbound')): ?>
|
<?php if (canEdit('outbound')): ?>
|
||||||
<button type="button" class="btn btn-sm btn-outline-primary"
|
<button class="btn btn-sm btn-white text-warning border" onclick='openMailModal("edit", <?= json_encode($mail) ?>)' title="تعديل">
|
||||||
onclick='openMailModal("edit", <?= json_encode($mail) ?>)' title="تعديل">
|
|
||||||
<i class="fas fa-edit"></i>
|
<i class="fas fa-edit"></i>
|
||||||
</button>
|
</button>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<?php if (canDelete('outbound')): ?>
|
<?php if (canDelete('outbound')): ?>
|
||||||
<a href="javascript:void(0)" onclick="confirmDelete(<?= $mail['id'] ?>)" class="btn btn-sm btn-outline-danger" title="حذف"><i class="fas fa-trash"></i></a>
|
<form method="POST" class="d-inline" onsubmit="return confirm('هل أنت متأكد من حذف هذا البريد؟');">
|
||||||
|
<input type="hidden" name="action" value="delete">
|
||||||
|
<input type="hidden" name="id" value="<?= $mail['id'] ?>">
|
||||||
|
<button type="submit" class="btn btn-sm btn-white text-danger border rounded-0" title="حذف">
|
||||||
|
<i class="fas fa-trash"></i>
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<?php endforeach; else: ?>
|
<?php endforeach; ?>
|
||||||
<tr>
|
|
||||||
<td colspan="9" class="text-center py-4 text-muted">لا يوجد بريد صادر مسجل حالياً</td>
|
|
||||||
</tr>
|
|
||||||
<?php endif; ?>
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<?php if ($total_pages > 1): ?>
|
|
||||||
<div class="card-footer bg-white border-0 py-3">
|
|
||||||
<nav aria-label="Page navigation">
|
|
||||||
<ul class="pagination justify-content-center mb-0">
|
|
||||||
<li class="page-item <?= ($page <= 1) ? 'disabled' : '' ?>">
|
|
||||||
<a class="page-link" href="?page=<?= $page - 1 ?><?= $search ? '&search='.urlencode($search) : '' ?><?= $my_tasks ? '&my_tasks=1' : '' ?>" aria-label="Previous">
|
|
||||||
<span aria-hidden="true">«</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<?php for ($i = 1; $i <= $total_pages; $i++): ?>
|
|
||||||
<li class="page-item <?= ($page == $i) ? 'active' : '' ?>">
|
|
||||||
<a class="page-link" href="?page=<?= $i ?><?= $search ? '&search='.urlencode($search) : '' ?><?= $my_tasks ? '&my_tasks=1' : '' ?>"><?= $i ?></a>
|
|
||||||
</li>
|
|
||||||
<?php endfor; ?>
|
|
||||||
<li class="page-item <?= ($page >= $total_pages) ? 'disabled' : '' ?>">
|
|
||||||
<a class="page-link" href="?page=<?= $page + 1 ?><?= $search ? '&search='.urlencode($search) : '' ?><?= $my_tasks ? '&my_tasks=1' : '' ?>" aria-label="Next">
|
|
||||||
<span aria-hidden="true">»</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</nav>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<?php if (canAdd('outbound') || canEdit('outbound')): ?>
|
<!-- Add/Edit Modal -->
|
||||||
<!-- Mail Modal -->
|
|
||||||
<div class="modal fade" id="mailModal" tabindex="-1" aria-labelledby="mailModalLabel" aria-hidden="true">
|
<div class="modal fade" id="mailModal" tabindex="-1" aria-labelledby="mailModalLabel" aria-hidden="true">
|
||||||
<div class="modal-dialog modal-lg">
|
<div class="modal-dialog modal-lg">
|
||||||
<div class="modal-content border-0 shadow">
|
<div class="modal-content border-0 shadow">
|
||||||
<div class="modal-header bg-success text-white">
|
<div class="modal-header bg-primary text-white py-3">
|
||||||
<h5 class="modal-title fw-bold" id="mailModalLabel">إضافة بريد صادر جديد</h5>
|
<h5 class="modal-title fw-bold" id="mailModalLabel">بريد صادر جديد</h5>
|
||||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
|
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
</div>
|
</div>
|
||||||
<form id="mailForm" method="POST" enctype="multipart/form-data">
|
<form id="mailForm" method="POST" enctype="multipart/form-data">
|
||||||
@ -407,92 +287,112 @@ function getStatusBadgeInList($mail) {
|
|||||||
<input type="hidden" name="id" id="modalId" value="0">
|
<input type="hidden" name="id" id="modalId" value="0">
|
||||||
|
|
||||||
<div class="row g-3">
|
<div class="row g-3">
|
||||||
<div class="col-md-4">
|
<div class="col-md-6">
|
||||||
<label class="form-label fw-bold">رقم القيد <span class="text-danger">*</span></label>
|
<label class="form-label small fw-bold">رقم القيد</label>
|
||||||
<input type="text" name="ref_no" id="modalRefNo" class="form-control" required readonly>
|
<input type="text" name="ref_no" id="modalRefNo" class="form-control" readonly required>
|
||||||
</div>
|
|
||||||
<div class="col-md-4">
|
|
||||||
<label class="form-label fw-bold">تاريخ التسجيل</label>
|
|
||||||
<input type="date" name="date_registered" id="modalDateRegistered" class="form-control">
|
|
||||||
</div>
|
|
||||||
<div class="col-md-4">
|
|
||||||
<label class="form-label fw-bold">الموعد النهائي</label>
|
|
||||||
<input type="date" name="due_date" id="modalDueDate" class="form-control">
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label class="form-label fw-bold">المستلم الخارجي (الجهة المستلمة)</label>
|
<label class="form-label small fw-bold">تاريخ التسجيل</label>
|
||||||
<input type="text" name="recipient" id="modalRecipient" class="form-control">
|
<input type="date" name="date_registered" id="modalDateRegistered" class="form-control" required>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label class="form-label fw-bold">المرسل الداخلي (القسم/الموظف)</label>
|
<label class="form-label small fw-bold">الجهة الصادر منها (الداخلية)</label>
|
||||||
<input type="text" name="sender" id="modalSender" class="form-control">
|
<input type="text" name="sender" id="modalSender" class="form-control" required placeholder="مثال: الشؤون القانونية">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12">
|
<div class="col-md-6">
|
||||||
<label class="form-label fw-bold">الموضوع <span class="text-danger">*</span></label>
|
<label class="form-label small fw-bold">الجهة المستلمة (الخارجية)</label>
|
||||||
|
<input type="text" name="recipient" id="modalRecipient" class="form-control" required placeholder="مثال: البنك المركزي">
|
||||||
|
</div>
|
||||||
|
<div class="col-md-12">
|
||||||
|
<label class="form-label small fw-bold">الموضوع</label>
|
||||||
<input type="text" name="subject" id="modalSubject" class="form-control" required>
|
<input type="text" name="subject" id="modalSubject" class="form-control" required>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12">
|
<div class="col-md-12">
|
||||||
<label class="form-label fw-bold">الوصف / ملاحظات</label>
|
<label class="form-label small fw-bold">محتوى الخطاب / الوصف</label>
|
||||||
<textarea name="description" id="description_editor" class="form-control" rows="5"></textarea>
|
<textarea name="description" id="description_editor" class="form-control" rows="5"></textarea>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12">
|
|
||||||
<label class="form-label fw-bold">المرفقات</label>
|
|
||||||
<input type="file" name="attachments[]" class="form-control" multiple>
|
|
||||||
<div id="modalExistingAttachments" class="mt-2"></div>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label class="form-label fw-bold">الحالة</label>
|
<label class="form-label small fw-bold">الحالة</label>
|
||||||
<select name="status_id" id="modalStatusId" class="form-select">
|
<select name="status_id" id="modalStatusId" class="form-select" required>
|
||||||
<?php foreach ($statuses_list as $s): ?>
|
<?php foreach ($statuses as $status): ?>
|
||||||
<?php
|
<option value="<?= $status['id'] ?>"><?= $status['name'] ?></option>
|
||||||
$d_name = $s['name'];
|
|
||||||
if ($d_name == 'received') $d_name = 'تم الاستلام';
|
|
||||||
if ($d_name == 'in_progress') $d_name = 'قيد المعالجة';
|
|
||||||
if ($d_name == 'closed') $d_name = 'مكتمل / مغلق';
|
|
||||||
?>
|
|
||||||
<option value="<?= $s['id'] ?>"><?= htmlspecialchars($d_name) ?></option>
|
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label class="form-label fw-bold">الموظف المسؤول</label>
|
<label class="form-label small fw-bold">إسناد للمتابعة (اختياري)</label>
|
||||||
<select name="assigned_to" id="modalAssignedTo" class="form-select">
|
<select name="assigned_to" id="modalAssignedTo" class="form-select">
|
||||||
<option value="">-- اختر موظف --</option>
|
<option value="">--- اختر مستخدم ---</option>
|
||||||
<?php foreach ($users_list as $u): ?>
|
<?php foreach ($users as $user): ?>
|
||||||
<option value="<?= $u['id'] ?>"><?= htmlspecialchars($u['full_name']) ?></option>
|
<option value="<?= $user['id'] ?>"><?= htmlspecialchars($user['full_name'] ?: $user['username']) ?></option>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-md-12 mt-4">
|
||||||
|
<div class="bg-light p-3 rounded">
|
||||||
|
<label class="form-label small fw-bold mb-2 d-block">المرفقات</label>
|
||||||
|
<input type="file" name="attachments[]" id="modalAttachmentsInput" class="form-control" multiple>
|
||||||
|
<div id="modalExistingAttachments" class="mt-2"></div>
|
||||||
|
<div id="modalSelectedAttachments" class="mt-1"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer bg-light">
|
</div>
|
||||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">إلغاء</button>
|
</div>
|
||||||
<button type="submit" class="btn btn-primary px-4">حفظ البيانات</button>
|
<div class="modal-footer bg-light border-0">
|
||||||
|
<button type="button" class="btn btn-white border px-4" data-bs-dismiss="modal">إلغاء</button>
|
||||||
|
<button type="submit" class="btn btn-primary px-4">حفظ الصادر</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
/* Custom Table Styles */
|
||||||
|
.table thead th {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.05rem;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #6c757d;
|
||||||
|
border-top: none;
|
||||||
|
padding: 1rem 0.5rem;
|
||||||
|
}
|
||||||
|
.btn-white {
|
||||||
|
background-color: #fff;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
.btn-white:hover {
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
}
|
||||||
|
.badge {
|
||||||
|
padding: 0.5em 0.8em;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
.input-group-text {
|
||||||
|
color: #adb5bd;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
let descriptionEditor;
|
|
||||||
let mailModal;
|
let mailModal;
|
||||||
|
|
||||||
function initEditors() {
|
function initEditors() {
|
||||||
if (typeof ClassicEditor === 'undefined') {
|
if (typeof tinymce === 'undefined') {
|
||||||
console.error('CKEditor not loaded');
|
console.error('TinyMCE not loaded');
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
const config = {
|
return tinymce.init({
|
||||||
|
selector: '#description_editor',
|
||||||
language: 'ar',
|
language: 'ar',
|
||||||
toolbar: ['heading', '|', 'bold', 'italic', 'link', 'bulletedList', 'numberedList', 'undo', 'redo']
|
directionality: 'rtl',
|
||||||
};
|
height: 300,
|
||||||
|
plugins: 'advlist autolink lists link image charmap preview anchor searchreplace visualblocks code fullscreen insertdatetime media table help wordcount',
|
||||||
return ClassicEditor.create(document.querySelector('#description_editor'), config)
|
toolbar: 'undo redo | fontfamily fontsize | bold italic underline strikethrough | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | removeformat | help',
|
||||||
.then(editor => { descriptionEditor = editor; })
|
font_size_formats: '8pt 10pt 12pt 14pt 18pt 24pt 36pt',
|
||||||
.catch(err => {
|
promotion: false,
|
||||||
console.error('CKEditor Init Error:', err);
|
branding: false
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -511,6 +411,8 @@ function openMailModal(action, data = null) {
|
|||||||
const modalAction = document.getElementById('modalAction');
|
const modalAction = document.getElementById('modalAction');
|
||||||
const modalId = document.getElementById('modalId');
|
const modalId = document.getElementById('modalId');
|
||||||
const existingAttachmentsDiv = document.getElementById('modalExistingAttachments');
|
const existingAttachmentsDiv = document.getElementById('modalExistingAttachments');
|
||||||
|
const selectedAttachmentsDiv = document.getElementById('modalSelectedAttachments');
|
||||||
|
const attachmentsInput = document.getElementById('modalAttachmentsInput');
|
||||||
|
|
||||||
const fields = {
|
const fields = {
|
||||||
ref_no: document.getElementById('modalRefNo'),
|
ref_no: document.getElementById('modalRefNo'),
|
||||||
@ -525,6 +427,8 @@ function openMailModal(action, data = null) {
|
|||||||
|
|
||||||
modalAction.value = action;
|
modalAction.value = action;
|
||||||
existingAttachmentsDiv.innerHTML = '';
|
existingAttachmentsDiv.innerHTML = '';
|
||||||
|
selectedAttachmentsDiv.innerHTML = '';
|
||||||
|
if (attachmentsInput) attachmentsInput.value = '';
|
||||||
|
|
||||||
if (action === 'add') {
|
if (action === 'add') {
|
||||||
label.textContent = 'إضافة بريد صادر جديد';
|
label.textContent = 'إضافة بريد صادر جديد';
|
||||||
@ -538,17 +442,23 @@ function openMailModal(action, data = null) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (descriptionEditor) descriptionEditor.setData('');
|
if (typeof tinymce !== 'undefined' && tinymce.get('description_editor')) {
|
||||||
else document.getElementById('description_editor').value = '';
|
tinymce.get('description_editor').setContent('');
|
||||||
} else {
|
} else {
|
||||||
label.textContent = 'تعديل البريد صادر';
|
document.getElementById('description_editor').value = '';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
label.textContent = 'تعديل البريد الصادر';
|
||||||
modalId.value = data.id;
|
modalId.value = data.id;
|
||||||
Object.keys(fields).forEach(key => {
|
Object.keys(fields).forEach(key => {
|
||||||
if (fields[key]) fields[key].value = data[key] || '';
|
if (fields[key]) fields[key].value = data[key] || '';
|
||||||
});
|
});
|
||||||
|
|
||||||
if (descriptionEditor) descriptionEditor.setData(data.description || '');
|
if (typeof tinymce !== 'undefined' && tinymce.get('description_editor')) {
|
||||||
else document.getElementById('description_editor').value = data.description || '';
|
tinymce.get('description_editor').setContent(data.description || '');
|
||||||
|
} else {
|
||||||
|
document.getElementById('description_editor').value = data.description || '';
|
||||||
|
}
|
||||||
|
|
||||||
// Display existing attachments
|
// Display existing attachments
|
||||||
if (data.attachment_names) {
|
if (data.attachment_names) {
|
||||||
@ -570,68 +480,37 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
<?php if ($deepLinkData): ?>
|
<?php if ($deepLinkData): ?>
|
||||||
openMailModal('edit', <?= json_encode($deepLinkData) ?>);
|
openMailModal('edit', <?= json_encode($deepLinkData) ?>);
|
||||||
<?php elseif ($error && isset($_POST['action'])): ?>
|
<?php elseif ($error && isset($_POST['action'])): ?>
|
||||||
const errorData = <?= json_encode([
|
const errorData = <?= json_encode($_POST) ?>;
|
||||||
'id' => $_POST['id'] ?? 0,
|
openMailModal(errorData.action, errorData);
|
||||||
'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_id' => $_POST['status_id'] ?? $default_status_id,
|
|
||||||
'assigned_to' => $_POST['assigned_to'] ?? '',
|
|
||||||
'attachment_names' => $_POST['attachment_names'] ?? ''
|
|
||||||
]) ?>;
|
|
||||||
openMailModal('<?= $_POST['action'] ?>', errorData);
|
|
||||||
<?php elseif (isset($_GET['action']) && $_GET['action'] === 'add'): ?>
|
|
||||||
openMailModal('add');
|
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Handle file selection display
|
||||||
|
const attachmentsInput = document.getElementById('modalAttachmentsInput');
|
||||||
|
if (attachmentsInput) {
|
||||||
|
attachmentsInput.addEventListener('change', function() {
|
||||||
|
const fileList = this.files;
|
||||||
|
const selectedAttachmentsDiv = document.getElementById('modalSelectedAttachments');
|
||||||
|
selectedAttachmentsDiv.innerHTML = '';
|
||||||
|
|
||||||
|
if (fileList.length > 0) {
|
||||||
|
let html = '<div class="mt-2"><p class="mb-1 fw-bold small text-primary">المرفقات المختارة للرفع:</p><ul class="list-unstyled small">';
|
||||||
|
for (let i = 0; i < fileList.length; i++) {
|
||||||
|
const fileSize = (fileList[i].size / 1024).toFixed(1);
|
||||||
|
html += `<li><i class="fas fa-file-upload me-1 text-primary"></i> ${fileList[i].name} <span class="text-muted">(${fileSize} KB)</span></li>`;
|
||||||
|
}
|
||||||
|
html += '</ul></div>';
|
||||||
|
selectedAttachmentsDiv.innerHTML = html;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
document.getElementById('mailForm').addEventListener('submit', function() {
|
document.getElementById('mailForm').addEventListener('submit', function() {
|
||||||
if (descriptionEditor) descriptionEditor.updateSourceElement();
|
if (typeof tinymce !== 'undefined') {
|
||||||
|
tinymce.triggerSave();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
function confirmDelete(id) {
|
|
||||||
if (typeof Swal === 'undefined') {
|
|
||||||
if (confirm('هل أنت متأكد من الحذف؟')) {
|
|
||||||
window.location.href = 'outbound.php?action=delete&id=' + id;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Swal.fire({
|
|
||||||
title: 'هل أنت متأكد؟',
|
|
||||||
text: "لا يمكن التراجع عن عملية الحذف!",
|
|
||||||
icon: 'warning',
|
|
||||||
showCancelButton: true,
|
|
||||||
confirmButtonColor: '#d33',
|
|
||||||
cancelButtonColor: '#3085d6',
|
|
||||||
confirmButtonText: 'نعم، احذف!',
|
|
||||||
cancelButtonText: 'إلغاء'
|
|
||||||
}).then((result) => {
|
|
||||||
if (result.isConfirmed) {
|
|
||||||
window.location.href = 'outbound.php?action=delete&id=' + id;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<style>
|
<?php require_once 'includes/footer.php'; ?>
|
||||||
.ck-editor__editable_inline {
|
|
||||||
min-height: 250px;
|
|
||||||
direction: rtl;
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
.modal-content {
|
|
||||||
border-radius: 15px;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
.modal-header.bg-success {
|
|
||||||
background-color: #198754 !important;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<?php require_once __DIR__ . '/includes/footer.php'; ?>
|
|
||||||
277
print_outbound.php
Normal file
277
print_outbound.php
Normal file
@ -0,0 +1,277 @@
|
|||||||
|
<?php
|
||||||
|
require_once __DIR__ . '/db/config.php';
|
||||||
|
require_once __DIR__ . '/includes/settings.php';
|
||||||
|
|
||||||
|
// Check if user is logged in
|
||||||
|
session_start();
|
||||||
|
if (!isset($_SESSION['user_id'])) {
|
||||||
|
die('Access Denied');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Basic permission check (matches header.php logic)
|
||||||
|
function isAdmin() {
|
||||||
|
if (isset($_SESSION['is_super_admin']) && $_SESSION['is_super_admin'] == 1) return true;
|
||||||
|
if (isset($_SESSION['user_role']) && strtolower($_SESSION['user_role']) === 'admin') return true;
|
||||||
|
if (isset($_SESSION['role']) && strtolower($_SESSION['role']) === 'admin') return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function canView($page) {
|
||||||
|
if (isAdmin()) return true;
|
||||||
|
return $_SESSION['permissions'][$page]['view'] ?? false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!canView('outbound')) {
|
||||||
|
die('Unauthorized access');
|
||||||
|
}
|
||||||
|
|
||||||
|
$id = isset($_GET['id']) ? (int)$_GET['id'] : 0;
|
||||||
|
if (!$id) {
|
||||||
|
die('Invalid ID');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch outbound mail details
|
||||||
|
$stmt = db()->prepare("SELECT * FROM outbound_mail WHERE id = ?");
|
||||||
|
$stmt->execute([$id]);
|
||||||
|
$mail = $stmt->fetch();
|
||||||
|
|
||||||
|
if (!$mail) {
|
||||||
|
die('Mail not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
$settings = get_settings();
|
||||||
|
$logo = !empty($settings['site_logo']) ? $settings['site_logo'] : '';
|
||||||
|
$site_name = $settings['site_name'];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert Gregorian date to Hijri
|
||||||
|
*/
|
||||||
|
function gregorianToHijri($date) {
|
||||||
|
if (!$date) return '';
|
||||||
|
$time = strtotime($date);
|
||||||
|
$m = date('m', $time);
|
||||||
|
$d = date('d', $time);
|
||||||
|
$y = date('Y', $time);
|
||||||
|
|
||||||
|
if (($y > 1582) || (($y == 1582) && ($m > 10)) || (($y == 1582) && ($m == 10) && ($d > 14))) {
|
||||||
|
$jd = (int)((1461 * ($y + 4800 + (int)(($m - 14) / 12))) / 4) +
|
||||||
|
(int)((367 * ($m - 2 - 12 * ((int)(($m - 14) / 12)))) / 12) -
|
||||||
|
(int)((3 * ((int)(($y + 4900 + (int)(($m - 14) / 12)) / 100))) / 4) +
|
||||||
|
$d - 32075;
|
||||||
|
} else {
|
||||||
|
$jd = 367 * $y - (int)((7 * ($y + 5001 + (int)(($m - 9) / 7))) / 4) + (int)((275 * $m) / 9) + $d + 1729777;
|
||||||
|
}
|
||||||
|
|
||||||
|
$l = $jd - 1948440 + 10632;
|
||||||
|
$n = (int)(($l - 1) / 10631);
|
||||||
|
$l = $l - 10631 * $n + 354;
|
||||||
|
$j = ((int)((10985 - $l) / 5316)) * ((int)((50 * $l) / 17719)) + ((int)($l / 5670)) * ((int)((43 * $l) / 15238));
|
||||||
|
$l = $l - ((int)((30 - $j) / 15)) * ((int)((17719 * $j) / 50)) - ((int)($j / 16)) * ((int)((15238 * $j) / 43)) + 29;
|
||||||
|
|
||||||
|
$month = (int)((24 * $l) / 709);
|
||||||
|
$day = $l - (int)((709 * $month) / 24);
|
||||||
|
$year = 30 * $n + $j - 30;
|
||||||
|
|
||||||
|
$hijriMonths = [
|
||||||
|
1 => "محرم", 2 => "صفر", 3 => "ربيع الأول", 4 => "ربيع الآخر",
|
||||||
|
5 => "جمادى الأولى", 6 => "جمادى الآخرة", 7 => "رجب", 8 => "شعبان",
|
||||||
|
9 => "رمضان", 10 => "شوال", 11 => "ذو القعدة", 12 => "ذو الحجة"
|
||||||
|
];
|
||||||
|
|
||||||
|
return $day . ' ' . $hijriMonths[$month] . ' ' . $year . ' هـ';
|
||||||
|
}
|
||||||
|
|
||||||
|
$hijriDate = gregorianToHijri($mail['date_registered']);
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="ar" dir="rtl">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>طباعة بريد صادر - <?= htmlspecialchars($mail['ref_no']) ?></title>
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Cairo:wght@400;700&display=swap" rel="stylesheet">
|
||||||
|
<style>
|
||||||
|
@page {
|
||||||
|
size: A4;
|
||||||
|
margin: 1.5cm;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
font-family: 'Cairo', 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||||
|
background-color: #fff;
|
||||||
|
color: #333;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
.print-container {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 21cm;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
.header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
border-bottom: 3px double #333;
|
||||||
|
padding-bottom: 20px;
|
||||||
|
margin-bottom: 40px;
|
||||||
|
}
|
||||||
|
.header-logo img {
|
||||||
|
max-height: 100px;
|
||||||
|
max-width: 200px;
|
||||||
|
}
|
||||||
|
.header-info {
|
||||||
|
text-align: left;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
.header-title {
|
||||||
|
text-align: center;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
.header-title h1 {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 28px;
|
||||||
|
color: #000;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
.mail-meta {
|
||||||
|
margin-bottom: 30px;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 20px;
|
||||||
|
background: #fff;
|
||||||
|
padding: 10px 0;
|
||||||
|
}
|
||||||
|
.meta-item {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 200px;
|
||||||
|
}
|
||||||
|
.meta-label {
|
||||||
|
font-weight: bold;
|
||||||
|
color: #444;
|
||||||
|
font-size: 14px;
|
||||||
|
display: inline-block;
|
||||||
|
width: 100px;
|
||||||
|
}
|
||||||
|
.meta-value {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #000;
|
||||||
|
border-bottom: 1px dotted #ccc;
|
||||||
|
padding-bottom: 2px;
|
||||||
|
}
|
||||||
|
.mail-content-container {
|
||||||
|
border: 1px solid #000;
|
||||||
|
padding: 30px;
|
||||||
|
min-height: 500px;
|
||||||
|
position: relative;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
.mail-content {
|
||||||
|
font-size: 16px;
|
||||||
|
text-align: justify;
|
||||||
|
}
|
||||||
|
.footer {
|
||||||
|
margin-top: 50px;
|
||||||
|
padding-top: 20px;
|
||||||
|
border-top: 1px solid #eee;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
.no-print {
|
||||||
|
position: fixed;
|
||||||
|
top: 20px;
|
||||||
|
left: 20px;
|
||||||
|
background: #212529;
|
||||||
|
color: #fff;
|
||||||
|
border: none;
|
||||||
|
padding: 10px 25px;
|
||||||
|
border-radius: 30px;
|
||||||
|
cursor: pointer;
|
||||||
|
z-index: 1000;
|
||||||
|
box-shadow: 0 4px 15px rgba(0,0,0,0.3);
|
||||||
|
font-family: 'Cairo', sans-serif;
|
||||||
|
font-weight: bold;
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
.no-print:hover {
|
||||||
|
background: #000;
|
||||||
|
transform: translateY(-2px);
|
||||||
|
}
|
||||||
|
@media print {
|
||||||
|
.no-print {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
background: none;
|
||||||
|
}
|
||||||
|
.print-container {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
.mail-content-container {
|
||||||
|
border: none;
|
||||||
|
padding: 10px 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<button class="no-print" onclick="window.print()">
|
||||||
|
<i class="fas fa-print me-1"></i> طباعة الوثيقة
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<div class="print-container">
|
||||||
|
<div class="header">
|
||||||
|
<div class="header-logo">
|
||||||
|
<?php if ($logo): ?>
|
||||||
|
<img src="<?= htmlspecialchars($logo) ?>" alt="Logo">
|
||||||
|
<?php else: ?>
|
||||||
|
<div style="font-weight: bold; font-size: 24px; color: #1a73e8;"><?= htmlspecialchars($site_name) ?></div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
<div class="header-title">
|
||||||
|
<!-- Title removed as per user request -->
|
||||||
|
</div>
|
||||||
|
<div class="header-info">
|
||||||
|
<!-- Date and time removed as per user request -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mail-meta">
|
||||||
|
<div class="meta-item">
|
||||||
|
<span class="meta-label">رقم القيد:</span>
|
||||||
|
<span class="meta-value"><?= htmlspecialchars($mail['ref_no']) ?></span>
|
||||||
|
</div>
|
||||||
|
<div class="meta-item" style="flex: 2;">
|
||||||
|
<span class="meta-label">التاريخ:</span>
|
||||||
|
<span class="meta-value">
|
||||||
|
<?= htmlspecialchars($hijriDate) ?>
|
||||||
|
الموافق:
|
||||||
|
<?= htmlspecialchars($mail['date_registered']) ?>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mail-content-container">
|
||||||
|
<div class="mail-content">
|
||||||
|
<?= $mail['description'] ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footer">
|
||||||
|
<p>
|
||||||
|
<?php if(!empty($settings['site_address'])): ?> العنوان: <?= htmlspecialchars($settings['site_address']) ?> | <?php endif; ?>
|
||||||
|
<?php if(!empty($settings['site_phone'])): ?> هاتف: <?= htmlspecialchars($settings['site_phone']) ?> | <?php endif; ?>
|
||||||
|
<?php if(!empty($settings['site_email'])): ?> بريد: <?= htmlspecialchars($settings['site_email']) ?><?php endif; ?>
|
||||||
|
</p>
|
||||||
|
<p>النظام الإلكتروني لإدارة البريد - <?= htmlspecialchars($site_name) ?></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@ -205,6 +205,9 @@ if ($type == 'internal') {
|
|||||||
<a href="<?= $back_link ?>" class="btn btn-outline-secondary">عودة للقائمة</a>
|
<a href="<?= $back_link ?>" class="btn btn-outline-secondary">عودة للقائمة</a>
|
||||||
<?php if ($type !== 'internal' && canEdit($type)): ?>
|
<?php if ($type !== 'internal' && canEdit($type)): ?>
|
||||||
<a href="<?= $type ?>.php?action=edit&id=<?= $mail['id'] ?>" class="btn btn-outline-primary">تعديل البيانات</a>
|
<a href="<?= $type ?>.php?action=edit&id=<?= $mail['id'] ?>" class="btn btn-outline-primary">تعديل البيانات</a>
|
||||||
|
<?php if ($type === 'outbound'): ?>
|
||||||
|
<a href="print_outbound.php?id=<?= $mail['id'] ?>" target="_blank" class="btn btn-outline-secondary"><i class="fas fa-print me-1"></i> طباعة</a>
|
||||||
|
<?php endif; ?>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user