adding editor

This commit is contained in:
Flatlogic Bot 2026-02-28 18:32:41 +00:00
parent 6ddb4f9f37
commit 627842bf5c
6 changed files with 986 additions and 881 deletions

View File

@ -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') {
$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]);
$mail_id = db()->lastInsertId();
if ($assigned_to) {
$should_notify = true;
}
$_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 = ? "); 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->execute([$ref_no, $date_registered, $due_date, $sender, $recipient, $subject, $description, $status_id, $assigned_to, $_SESSION['user_id']]);
$id = db()->lastInsertId();
$success = 'تم إضافة البريد الوارد بنجاح.';
} else {
if (!canEdit('inbound')) throw new Exception('ليس لديك صلاحية التعديل.');
$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 Attachments // Handle file uploads
if (!empty($_FILES['attachments']['name'][0])) { if (isset($_FILES['attachments']) && !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') {
if (!canDelete('inbound')) {
redirect('inbound.php'); $error = 'ليس لديك صلاحية الحذف.';
} catch (PDOException $e) { } else {
if (db()->inTransaction()) db()->rollBack(); $stmt = db()->prepare("DELETE FROM inbound_mail WHERE id = ?");
if ($e->getCode() == 23000) { $stmt->execute([$id]);
$error = 'رقم القيد مستخدم مسبقاً'; $success = 'تم حذف البريد الوارد بنجاح.';
} else {
$error = 'حدث خطأ: ' . $e->getMessage();
}
} }
} else {
$error = 'يرجى ملء الحقول المطلوبة (رقم القيد، الموضوع)';
} }
} }
} }
// Delete action // Fetch stats
if (isset($_GET['action']) && $_GET['action'] === 'delete' && isset($_GET['id'])) { $total_stmt = db()->query("SELECT COUNT(*) FROM inbound_mail");
if (!canDelete('inbound')) { $total_inbound = $total_stmt->fetchColumn();
$error = 'عذراً، ليس لديك الصلاحية لحذف السجلات';
} else {
$id = $_GET['id'];
$stmt = db()->prepare("DELETE FROM inbound_mail WHERE id = ? ");
$stmt->execute([$id]);
$_SESSION['success'] = 'تم حذف البريد بنجاح';
redirect('inbound.php');
}
}
// Get session messages $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 '%قيد%')");
if (isset($_SESSION['success'])) { $pending_stmt->execute();
$success = $_SESSION['success']; $pending_inbound = $pending_stmt->fetchColumn();
unset($_SESSION['success']);
}
if (isset($_SESSION['error'])) {
$error = $_SESSION['error'];
unset($_SESSION['error']);
}
$search = $_GET['search'] ?? ''; // Search and Filter
$my_tasks = isset($_GET['my_tasks']) && $_GET['my_tasks'] == 1; $where = "WHERE 1=1";
// Pagination settings
$limit = 10; // Items per page
$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">
<?php if (canAdd('inbound')): ?> <div class="col-md-8">
<button type="button" class="btn btn-primary shadow-sm" onclick="openMailModal('add')"> <h2 class="fw-bold mb-1"><i class="fas fa-download text-primary me-2"></i> البريد الوارد</h2>
<i class="fas fa-plus-circle me-1"></i> إضافة جديد <p class="text-muted">إدارة جميع المراسلات الواردة والمهام المسندة.</p>
</button> </div>
<?php endif; ?> <div class="col-md-4 text-md-end d-flex align-items-center justify-content-md-end gap-2">
</div> <?php if (canAdd('inbound')): ?>
<button class="btn btn-primary px-4 py-2" onclick="openMailModal('add')">
<?php if ($success): ?> <i class="fas fa-plus me-1"></i> إضافة بريد جديد
<div class="alert alert-success alert-dismissible fade show" role="alert"> </button>
<?= $success ?>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
<?php endif; ?>
<?php if ($error): ?>
<div class="alert alert-danger alert-dismissible fade show" role="alert">
<?= $error ?>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</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 class="col-md-3">
<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()">
<label class="form-check-label fw-bold" for="myTasksSwitch">مهامي فقط</label>
</div>
</div>
<div class="col-auto">
<button type="submit" class="btn btn-secondary px-4">بحث</button>
</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; ?> <?php endif; ?>
</form> </div>
</div> </div>
<div class="card-body p-0">
<!-- 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): ?>
<div class="alert alert-danger shadow-sm border-0 mb-4"><?= $error ?></div>
<?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-4">
<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 class="col-md-3">
<div class="form-check form-switch mt-1">
<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 ms-2" for="myTasks">مهامي فقط</label>
</div>
</div>
<div class="col-md-2 text-end">
<button type="submit" class="btn btn-light w-100">تصفية</button>
</div>
</form>
</div>
</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']): ?>
<span class="<?= (strtotime($mail['due_date']) < time() && $mail['status_name'] != 'closed') ? 'text-danger fw-bold' : '' ?>">
<?= $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; ?>
</span>
<?php else: ?>
<span class="text-muted">-</span>
<?php endif; ?>
</td> </td>
<td><?= htmlspecialchars($mail['subject']) ?></td>
<td><?= htmlspecialchars($mail['sender']) ?></td>
<td>
<?php if (!empty($mail['attachment_names'])): ?>
<small class="text-muted"><i class="fas fa-paperclip me-1"></i> <?= htmlspecialchars(str_replace('|||', ', ', $mail['attachment_names'])) ?></small>
<?php else: ?>
<span class="text-muted">-</span>
<?php endif; ?>
</td>
<td>
<?php if ($mail['assigned_to_name']): ?>
<span class="text-nowrap"><i class="fas fa-user-tag me-1 text-muted"></i> <?= htmlspecialchars($mail['assigned_to_name']) ?></span>
<?php else: ?>
<span class="text-muted">غير معين</span>
<?php endif; ?>
</td>
<td><?= getStatusBadgeInList($mail) ?></td>
<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('inbound')): ?>
<button type="button" class="btn btn-sm btn-outline-primary"
onclick='openMailModal("edit", <?= json_encode($mail) ?>)' title="تعديل">
<i class="fas fa-edit"></i>
</button>
<?php endif; ?>
<?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>
<?php endif; ?>
</td>
</tr>
<?php endforeach; else: ?>
<tr>
<td colspan="9" class="text-center py-4 text-muted">لا يوجد بريد وارد مسجل حالياً</td>
</tr> </tr>
<?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>
<?php endif; ?>
</td>
<td><?= htmlspecialchars($mail['sender']) ?></td>
<td>
<span class="badge rounded-pill" style="background-color: <?= $mail['status_color'] ?>20; color: <?= $mail['status_color'] ?>;">
<i class="fas fa-circle me-1 small"></i> <?= htmlspecialchars($mail['status_name']) ?>
</span>
</td>
<td>
<div class="d-flex align-items-center">
<div class="rounded-circle bg-light d-flex align-items-center justify-content-center me-2" style="width: 24px; height: 24px;">
<i class="fas fa-user-circle text-muted small"></i>
</div>
<span class="small"><?= htmlspecialchars($mail['assigned_to_name'] ?: 'غير محدد') ?></span>
</div>
</td>
<td class="text-center pe-4">
<div class="btn-group shadow-sm rounded">
<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')): ?>
<button class="btn btn-sm btn-white text-warning border" onclick='openMailModal("edit", <?= json_encode($mail) ?>)' title="تعديل">
<i class="fas fa-edit"></i>
</button>
<?php endif; ?>
<?php if (canDelete('inbound')): ?>
<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; ?>
</div>
</td>
</tr>
<?php endforeach; ?>
</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">&laquo;</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">&raquo;</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> </div>
<div class="modal-footer bg-light"> <div class="modal-footer bg-light border-0">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">إلغاء</button> <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,26 +368,53 @@ 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
}); });
} }
function openMailModal(action, data = null) { function openMailModal(action, data = null) {
@ -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'; ?>

View File

@ -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 -->

View File

@ -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();
@ -350,4 +379,4 @@ document.addEventListener('DOMContentLoaded', function() {
}); });
</script> </script>
<?php require_once __DIR__ . '/includes/footer.php'; ?> <?php require_once __DIR__ . '/includes/footer.php'; ?>

View File

@ -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') {
$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]);
$mail_id = db()->lastInsertId();
if ($assigned_to) {
$should_notify = true;
}
$_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 = ? "); if ($action === 'add') {
$stmt->execute([$ref_no, $date_registered, $due_date, $sender, $recipient, $subject, $description, $status_id, $assigned_to, $mail_id]); 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 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
if ($assigned_to && $assigned_to != $old_assigned_to) { $stmt->execute([$ref_no, $date_registered, $due_date, $sender, $recipient, $subject, $description, $status_id, $assigned_to, $_SESSION['user_id']]);
$should_notify = true; $id = db()->lastInsertId();
} $success = 'تم إضافة البريد الصادر بنجاح.';
} else {
$_SESSION['success'] = 'تم تحديث البيانات بنجاح'; if (!canEdit('outbound')) throw new Exception('ليس لديك صلاحية التعديل.');
$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, $id]);
$success = 'تم تحديث بيانات البريد الصادر بنجاح.';
} }
// Handle Attachments // Handle file uploads
if (!empty($_FILES['attachments']['name'][0])) { if (isset($_FILES['attachments']) && !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') {
if (!canDelete('outbound')) {
redirect('outbound.php'); $error = 'ليس لديك صلاحية الحذف.';
} catch (PDOException $e) { } else {
if (db()->inTransaction()) db()->rollBack(); $stmt = db()->prepare("DELETE FROM outbound_mail WHERE id = ?");
if ($e->getCode() == 23000) { $stmt->execute([$id]);
$error = 'رقم القيد مستخدم مسبقاً'; $success = 'تم حذف البريد الصادر بنجاح.';
} else {
$error = 'حدث خطأ: ' . $e->getMessage();
}
} }
} else {
$error = 'يرجى ملء الحقول المطلوبة (رقم القيد، الموضوع)';
} }
} }
} }
// Delete action // Fetch stats
if (isset($_GET['action']) && $_GET['action'] === 'delete' && isset($_GET['id'])) { $total_stmt = db()->query("SELECT COUNT(*) FROM outbound_mail");
if (!canDelete('outbound')) { $total_outbound = $total_stmt->fetchColumn();
$error = 'عذراً، ليس لديك الصلاحية لحذف السجلات';
} else {
$id = $_GET['id'];
$stmt = db()->prepare("DELETE FROM outbound_mail WHERE id = ? ");
$stmt->execute([$id]);
$_SESSION['success'] = 'تم حذف البريد بنجاح';
redirect('outbound.php');
}
}
// Get session messages $completed_stmt = db()->prepare("SELECT COUNT(*) FROM outbound_mail WHERE status_id IN (SELECT id FROM mailbox_statuses WHERE name LIKE '%مكتمل%' OR name LIKE '%منتهي%')");
if (isset($_SESSION['success'])) { $completed_stmt->execute();
$success = $_SESSION['success']; $completed_outbound = $completed_stmt->fetchColumn();
unset($_SESSION['success']);
}
if (isset($_SESSION['error'])) {
$error = $_SESSION['error'];
unset($_SESSION['error']);
}
$search = $_GET['search'] ?? ''; // Search and Filter
$my_tasks = isset($_GET['my_tasks']) && $_GET['my_tasks'] == 1; $where = "WHERE 1=1";
// Pagination settings
$limit = 10; // Items per page
$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">
<?php if (canAdd('outbound')): ?> <div class="col-md-8">
<button type="button" class="btn btn-primary shadow-sm" onclick="openMailModal('add')"> <h2 class="fw-bold mb-1"><i class="fas fa-upload text-primary me-2"></i> البريد الصادر</h2>
<i class="fas fa-plus-circle me-1"></i> إضافة جديد <p class="text-muted">إدارة المراسلات الصادرة إلى الجهات الخارجية وتتبع حالاتها.</p>
</button> </div>
<?php endif; ?> <div class="col-md-4 text-md-end d-flex align-items-center justify-content-md-end gap-2">
</div> <?php if (canAdd('outbound')): ?>
<button class="btn btn-primary px-4 py-2" onclick="openMailModal('add')">
<?php if ($success): ?> <i class="fas fa-plus me-1"></i> إضافة صادر جديد
<div class="alert alert-success alert-dismissible fade show" role="alert"> </button>
<?= $success ?>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
<?php endif; ?>
<?php if ($error): ?>
<div class="alert alert-danger alert-dismissible fade show" role="alert">
<?= $error ?>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</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 class="col-md-3">
<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()">
<label class="form-check-label fw-bold" for="myTasksSwitch">مهامي فقط</label>
</div>
</div>
<div class="col-auto">
<button type="submit" class="btn btn-secondary px-4">بحث</button>
</div>
<?php if ($search || $my_tasks): ?>
<div class="col-auto">
<a href="outbound.php" class="btn btn-link text-decoration-none">إلغاء التصفية</a>
</div>
<?php endif; ?> <?php endif; ?>
</form> </div>
</div> </div>
<div class="card-body p-0">
<!-- 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-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>
<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-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>
</div>
<?php if ($error): ?>
<div class="alert alert-danger shadow-sm border-0 mb-4"><?= $error ?></div>
<?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>
</div>
</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']): ?>
<span class="<?= (strtotime($mail['due_date']) < time() && $mail['status_name'] != 'closed') ? 'text-danger fw-bold' : '' ?>">
<?= $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; ?>
</span>
<?php else: ?>
<span class="text-muted">-</span>
<?php endif; ?>
</td> </td>
<td><?= truncate_text($mail['subject'], 80) ?></td>
<td><?= htmlspecialchars($mail['recipient']) ?></td>
<td>
<?php if (!empty($mail['attachment_names'])): ?>
<small class="text-muted"><i class="fas fa-paperclip me-1"></i> <?= htmlspecialchars(str_replace('|||', ', ', $mail['attachment_names'])) ?></small>
<?php else: ?>
<span class="text-muted">-</span>
<?php endif; ?>
</td>
<td>
<?php if ($mail['assigned_to_name']): ?>
<span class="text-nowrap"><i class="fas fa-user-tag me-1 text-muted"></i> <?= htmlspecialchars($mail['assigned_to_name']) ?></span>
<?php else: ?>
<span class="text-muted">غير معين</span>
<?php endif; ?>
</td>
<td><?= getStatusBadgeInList($mail) ?></td>
<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')): ?>
<button type="button" class="btn btn-sm btn-outline-primary"
onclick='openMailModal("edit", <?= json_encode($mail) ?>)' title="تعديل">
<i class="fas fa-edit"></i>
</button>
<?php endif; ?>
<?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>
<?php endif; ?>
</td>
</tr>
<?php endforeach; else: ?>
<tr>
<td colspan="9" class="text-center py-4 text-muted">لا يوجد بريد صادر مسجل حالياً</td>
</tr> </tr>
<?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>
<?php endif; ?>
</td>
<td><?= htmlspecialchars($mail['recipient']) ?></td>
<td>
<span class="badge rounded-pill" style="background-color: <?= $mail['status_color'] ?>20; color: <?= $mail['status_color'] ?>;">
<i class="fas fa-circle me-1 small"></i> <?= htmlspecialchars($mail['status_name']) ?>
</span>
</td>
<td class="text-center pe-4">
<div class="btn-group shadow-sm rounded">
<a href="view_mail.php?id=<?= $mail['id'] ?>&type=outbound" class="btn btn-sm btn-white text-primary border" title="عرض">
<i class="fas fa-eye"></i>
</a>
<a href="print_outbound.php?id=<?= $mail['id'] ?>" target="_blank" class="btn btn-sm btn-white text-secondary border" title="طباعة">
<i class="fas fa-print"></i>
</a>
<?php if (canEdit('outbound')): ?>
<button class="btn btn-sm btn-white text-warning border" onclick='openMailModal("edit", <?= json_encode($mail) ?>)' title="تعديل">
<i class="fas fa-edit"></i>
</button>
<?php endif; ?>
<?php if (canDelete('outbound')): ?>
<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; ?>
</div>
</td>
</tr>
<?php endforeach; ?>
</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">&laquo;</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">&raquo;</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,93 +287,113 @@ 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> </div>
<div class="modal-footer bg-light"> <div class="modal-footer bg-light border-0">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">إلغاء</button> <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>
</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
}); });
} }
function openMailModal(action, data = null) { function openMailModal(action, data = null) {
@ -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 = 'إضافة بريد صادر جديد';
@ -537,18 +441,24 @@ function openMailModal(action, data = null) {
else fields[key].value = ''; else fields[key].value = '';
} }
}); });
if (descriptionEditor) descriptionEditor.setData(''); if (typeof tinymce !== 'undefined' && tinymce.get('description_editor')) {
else document.getElementById('description_editor').value = ''; tinymce.get('description_editor').setContent('');
} else {
document.getElementById('description_editor').value = '';
}
} else { } else {
label.textContent = 'تعديل البريد صادر'; 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
View 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>

View File

@ -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>