paginations

This commit is contained in:
Flatlogic Bot 2026-02-28 02:29:08 +00:00
parent 118aae16b0
commit 21d9204f3a
4 changed files with 173 additions and 24 deletions

View File

@ -0,0 +1,3 @@
-- Migration: Add referred_user_id to comments
ALTER TABLE comments ADD COLUMN referred_user_id INT DEFAULT NULL;
ALTER TABLE comments ADD CONSTRAINT fk_comments_referred_user FOREIGN KEY (referred_user_id) REFERENCES users(id) ON DELETE SET NULL;

View File

@ -123,26 +123,45 @@ if (isset($_GET['action']) && $_GET['action'] === 'delete' && isset($_GET['id'])
$search = $_GET['search'] ?? '';
$my_tasks = isset($_GET['my_tasks']) && $_GET['my_tasks'] == 1;
$query = "SELECT m.*, s.name as status_name, s.color as status_color, u.full_name as assigned_to_name
FROM mailbox m
LEFT JOIN mailbox_statuses s ON m.status_id = s.id
LEFT JOIN users u ON m.assigned_to = u.id
WHERE m.type = 'inbound'";
// 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 = ["m.type = 'inbound'"];
$params = [];
if ($search) {
$query .= " AND (m.ref_no LIKE ? OR m.sender LIKE ? OR m.subject LIKE ?)";
$where_clauses[] = "(m.ref_no LIKE ? OR m.sender LIKE ? OR m.subject LIKE ?)";
$params[] = "%$search%";
$params[] = "%$search%";
$params[] = "%$search%";
}
if ($my_tasks) {
$query .= " AND m.assigned_to = ?";
$where_clauses[] = "m.assigned_to = ?";
$params[] = $user_id;
}
$query .= " ORDER BY m.created_at DESC";
$where_sql = implode(" AND ", $where_clauses);
// Get total records for pagination
$count_query = "SELECT COUNT(*) FROM mailbox 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
FROM mailbox m
LEFT JOIN mailbox_statuses s ON m.status_id = s.id
LEFT JOIN users u ON m.assigned_to = u.id
WHERE $where_sql
ORDER BY m.created_at DESC
LIMIT $limit OFFSET $offset";
$stmt = db()->prepare($query);
$stmt->execute($params);
$mails = $stmt->fetchAll();
@ -284,6 +303,29 @@ function getStatusBadgeInList($mail) {
</table>
</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>
<?php if (canAdd() || canEdit()): ?>
@ -471,4 +513,4 @@ function confirmDelete(id) {
}
</style>
<?php require_once __DIR__ . '/includes/footer.php'; ?>
<?php require_once __DIR__ . '/includes/footer.php'; ?>

View File

@ -159,26 +159,45 @@ if (isset($_GET['action']) && $_GET['action'] === 'delete' && isset($_GET['id'])
$search = $_GET['search'] ?? '';
$my_tasks = isset($_GET['my_tasks']) && $_GET['my_tasks'] == 1;
$query = "SELECT m.*, s.name as status_name, s.color as status_color, u.full_name as assigned_to_name
FROM mailbox m
LEFT JOIN mailbox_statuses s ON m.status_id = s.id
LEFT JOIN users u ON m.assigned_to = u.id
WHERE m.type = 'outbound'";
// 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 = ["m.type = 'outbound'"];
$params = [];
if ($search) {
$query .= " AND (m.ref_no LIKE ? OR m.recipient LIKE ? OR m.subject LIKE ?)";
$where_clauses[] = "(m.ref_no LIKE ? OR m.recipient LIKE ? OR m.subject LIKE ?)";
$params[] = "%$search%";
$params[] = "%$search%";
$params[] = "%$search%";
}
if ($my_tasks) {
$query .= " AND m.assigned_to = ?";
$where_clauses[] = "m.assigned_to = ?";
$params[] = $user_id;
}
$query .= " ORDER BY m.created_at DESC";
$where_sql = implode(" AND ", $where_clauses);
// Get total records for pagination
$count_query = "SELECT COUNT(*) FROM mailbox 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
FROM mailbox m
LEFT JOIN mailbox_statuses s ON m.status_id = s.id
LEFT JOIN users u ON m.assigned_to = u.id
WHERE $where_sql
ORDER BY m.created_at DESC
LIMIT $limit OFFSET $offset";
$stmt = db()->prepare($query);
$stmt->execute($params);
$mails = $stmt->fetchAll();
@ -320,6 +339,29 @@ function getStatusBadgeInList($mail) {
</table>
</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>
<?php if (canAdd() || canEdit()): ?>
@ -545,4 +587,4 @@ function confirmDelete(id) {
}
</style>
<?php require_once __DIR__ . '/includes/footer.php'; ?>
<?php require_once __DIR__ . '/includes/footer.php'; ?>

View File

@ -1,5 +1,6 @@
<?php
require_once __DIR__ . '/includes/header.php';
require_once __DIR__ . '/mail/MailService.php';
// Check if user has view permission
if (!canView()) {
@ -30,9 +31,43 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['add_comment'])) {
$error = 'عذراً، ليس لديك الصلاحية لإضافة تعليقات';
} else {
$comment = $_POST['comment'] ?? '';
$referred_user_id = $_POST['referred_user_id'] ?: null;
if ($comment) {
$stmt = db()->prepare("INSERT INTO comments (mail_id, user_id, comment) VALUES (?, ?, ?)");
$stmt->execute([$id, $_SESSION['user_id'], $comment]);
$stmt = db()->prepare("INSERT INTO comments (mail_id, user_id, comment, referred_user_id) VALUES (?, ?, ?, ?)");
$stmt->execute([$id, $_SESSION['user_id'], $comment, $referred_user_id]);
// Send email notification if referred
if ($referred_user_id) {
$stmt_u = db()->prepare("SELECT email, full_name FROM users WHERE id = ?");
$stmt_u->execute([$referred_user_id]);
$referred_user = $stmt_u->fetch();
if ($referred_user && !empty($referred_user['email'])) {
$sender_name = $_SESSION['full_name'] ?? 'زميلك';
$mail_subject = "إحالة بريد: " . $mail['subject'];
$mail_link = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http") . "://$_SERVER[HTTP_HOST]" . dirname($_SERVER['PHP_SELF']) . "/view_mail.php?id=" . $id;
$html = "
<h3>مرحباً " . htmlspecialchars($referred_user['full_name']) . "</h3>
<p>قام <strong>" . htmlspecialchars($sender_name) . "</strong> بإحالة بريد إليك مع التعليق التالي:</p>
<blockquote style='background: #f9f9f9; padding: 10px; border-left: 5px solid #ccc;'>
" . nl2br(htmlspecialchars($comment)) . "
</blockquote>
<p><strong>تفاصيل البريد:</strong></p>
<ul>
<li><strong>رقم القيد:</strong> " . htmlspecialchars($mail['ref_no']) . "</li>
<li><strong>الموضوع:</strong> " . htmlspecialchars($mail['subject']) . "</li>
</ul>
<p><a href='{$mail_link}' style='display: inline-block; padding: 10px 20px; background-color: #007bff; color: white; text-decoration: none; border-radius: 5px;'>عرض البريد</a></p>
";
$txt = "قام {$sender_name} بإحالة بريد إليك: {$mail['subject']}\n\nالتعليق: {$comment}\n\nعرض البريد: {$mail_link}";
MailService::sendMail($referred_user['email'], $mail_subject, $html, $txt);
}
}
$success = 'تم إضافة التعليق بنجاح';
}
}
@ -89,7 +124,11 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['delete_attachment']))
}
}
$comments = db()->prepare("SELECT c.*, u.full_name FROM comments c LEFT JOIN users u ON c.user_id = u.id WHERE c.mail_id = ? ORDER BY c.created_at DESC");
$comments = db()->prepare("SELECT c.*, u.full_name, ru.full_name as referred_name
FROM comments c
LEFT JOIN users u ON c.user_id = u.id
LEFT JOIN users ru ON c.referred_user_id = ru.id
WHERE c.mail_id = ? ORDER BY c.created_at DESC");
$comments->execute([$id]);
$mail_comments = $comments->fetchAll();
@ -97,6 +136,11 @@ $attachments = db()->prepare("SELECT * FROM attachments WHERE mail_id = ? ORDER
$attachments->execute([$id]);
$mail_attachments = $attachments->fetchAll();
// Fetch all users for referral dropdown (excluding current user)
$stmt_users = db()->prepare("SELECT id, full_name, role FROM users WHERE id != ? ORDER BY full_name ASC");
$stmt_users->execute([$_SESSION['user_id']]);
$all_users = $stmt_users->fetchAll();
// Helper to check previewable files
function isPreviewable($fileName) {
$ext = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
@ -225,11 +269,22 @@ function isPreviewable($fileName) {
</div>
<div class="card-body">
<?php if (canEdit()): ?>
<form method="POST" class="mb-4">
<form method="POST" class="mb-4 bg-light p-3 rounded border">
<div class="mb-2">
<label class="form-label small fw-bold">إضافة تعليق</label>
<textarea name="comment" class="form-control" rows="2" placeholder="أضف تعليقاً أو ملاحظة متابعة..." required></textarea>
</div>
<button type="submit" name="add_comment" class="btn btn-sm btn-primary">إرسال تعليق</button>
<div class="mb-3">
<label class="form-label small fw-bold">إحالة إلى موظف (اختياري)</label>
<select name="referred_user_id" class="form-select form-select-sm">
<option value="">-- اختر موظفاً للإحالة --</option>
<?php foreach ($all_users as $u): ?>
<option value="<?= $u['id'] ?>"><?= htmlspecialchars($u['full_name']) ?> (<?= ucfirst($u['role']) ?>)</option>
<?php endforeach; ?>
</select>
<div class="form-text small">سيتم إرسال تنبيه عبر البريد الإلكتروني للموظف المحال إليه.</div>
</div>
<button type="submit" name="add_comment" class="btn btn-sm btn-primary">إرسال تعليق وإحالة</button>
</form>
<?php endif; ?>
@ -237,7 +292,14 @@ function isPreviewable($fileName) {
<?php if ($mail_comments): foreach ($mail_comments as $c): ?>
<div class="border-bottom pb-2 mb-2">
<div class="d-flex justify-content-between">
<span class="fw-bold text-primary"><?= htmlspecialchars($c['full_name']) ?></span>
<div>
<span class="fw-bold text-primary"><?= htmlspecialchars($c['full_name']) ?></span>
<?php if ($c['referred_name']): ?>
<span class="badge bg-info text-dark ms-2 small">
<i class="fas fa-share ms-1"></i> إحالة إلى: <?= htmlspecialchars($c['referred_name']) ?>
</span>
<?php endif; ?>
</div>
<span class="text-muted small"><?= $c['created_at'] ?></span>
</div>
<p class="mb-0 small"><?= nl2br(htmlspecialchars($c['comment'])) ?></p>