add paginations
This commit is contained in:
parent
4ee179ebfe
commit
1b3577b917
75
expenses.php
75
expenses.php
@ -1,6 +1,7 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/includes/header.php';
|
||||
require_once __DIR__ . '/includes/accounting_functions.php'; // Include accounting helpers
|
||||
require_once __DIR__ . '/includes/pagination.php';
|
||||
|
||||
if (!canView('expenses')) {
|
||||
redirect('index.php');
|
||||
@ -152,28 +153,56 @@ $date_to = $_GET['date_to'] ?? date('Y-m-t');
|
||||
$category_filter = $_GET['category_id'] ?? '';
|
||||
$search = $_GET['search'] ?? '';
|
||||
|
||||
// Build WHERE clause
|
||||
$whereConditions = ["e.date BETWEEN ? AND ?"];
|
||||
$params = [$date_from, $date_to];
|
||||
|
||||
if ($category_filter) {
|
||||
$whereConditions[] = "e.category_id = ?";
|
||||
$params[] = $category_filter;
|
||||
}
|
||||
if ($search) {
|
||||
$whereConditions[] = "(e.description LIKE ? OR e.vendor LIKE ? OR e.reference LIKE ?)";
|
||||
$params[] = "%$search%";
|
||||
$params[] = "%$search%";
|
||||
$params[] = "%$search%";
|
||||
}
|
||||
|
||||
$whereClause = implode(' AND ', $whereConditions);
|
||||
|
||||
// Pagination
|
||||
$page = $_GET['page'] ?? 1;
|
||||
$perPage = 10;
|
||||
|
||||
// Count Total Items & Sum Total Amount
|
||||
$countSql = "SELECT COUNT(*) as count, SUM(amount) as total_amount FROM expenses e WHERE $whereClause";
|
||||
$countStmt = db()->prepare($countSql);
|
||||
$countStmt->execute($params);
|
||||
$countResult = $countStmt->fetch(PDO::FETCH_ASSOC);
|
||||
$totalExpenses = $countResult['count'];
|
||||
$grandTotalAmount = $countResult['total_amount'] ?? 0;
|
||||
|
||||
$pagination = getPagination($page, $totalExpenses, $perPage);
|
||||
|
||||
// Fetch Items
|
||||
$sql = "SELECT e.*, c.name as category_name, u.username as created_by_name
|
||||
FROM expenses e
|
||||
LEFT JOIN expense_categories c ON e.category_id = c.id
|
||||
LEFT JOIN users u ON e.user_id = u.id
|
||||
WHERE e.date BETWEEN ? AND ?";
|
||||
$params = [$date_from, $date_to];
|
||||
WHERE $whereClause
|
||||
ORDER BY e.date DESC, e.id DESC
|
||||
LIMIT ? OFFSET ?";
|
||||
|
||||
if ($category_filter) {
|
||||
$sql .= " AND e.category_id = ?";
|
||||
$params[] = $category_filter;
|
||||
}
|
||||
if ($search) {
|
||||
$sql .= " AND (e.description LIKE ? OR e.vendor LIKE ? OR e.reference LIKE ?)";
|
||||
$params[] = "%$search%";
|
||||
$params[] = "%$search%";
|
||||
$params[] = "%$search%";
|
||||
}
|
||||
|
||||
$sql .= " ORDER BY e.date DESC, e.id DESC";
|
||||
// Add LIMIT/OFFSET to params
|
||||
$params[] = $pagination['limit'];
|
||||
$params[] = $pagination['offset'];
|
||||
|
||||
$stmt = db()->prepare($sql);
|
||||
$stmt->execute($params);
|
||||
foreach ($params as $k => $v) {
|
||||
$type = is_int($v) ? PDO::PARAM_INT : PDO::PARAM_STR;
|
||||
$stmt->bindValue($k + 1, $v, $type);
|
||||
}
|
||||
$stmt->execute();
|
||||
$expenses = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
// Fetch Categories for Dropdown
|
||||
@ -299,9 +328,16 @@ if (isset($_SESSION['success'])) {
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<tr class="bg-light fw-bold">
|
||||
<td colspan="4" class="text-end">الإجمالي:</td>
|
||||
<td class="text-danger"><?= number_format(array_sum(array_column($expenses, 'amount')), 2) ?></td>
|
||||
<!-- Page Total -->
|
||||
<tr class="bg-light">
|
||||
<td colspan="4" class="text-end fw-bold">إجمالي الصفحة:</td>
|
||||
<td class="text-danger fw-bold"><?= number_format(array_sum(array_column($expenses, 'amount')), 2) ?></td>
|
||||
<td colspan="3"></td>
|
||||
</tr>
|
||||
<!-- Grand Total -->
|
||||
<tr class="bg-light border-top-0">
|
||||
<td colspan="4" class="text-end fw-bold">الإجمالي الكلي (للبحث الحالي):</td>
|
||||
<td class="text-danger fw-bold"><?= number_format($grandTotalAmount, 2) ?></td>
|
||||
<td colspan="3"></td>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
@ -309,6 +345,9 @@ if (isset($_SESSION['success'])) {
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer bg-white">
|
||||
<?= renderPagination($pagination['current_page'], $pagination['total_pages']) ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal -->
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
<?php
|
||||
require_once 'includes/header.php';
|
||||
require_once __DIR__ . '/includes/pagination.php';
|
||||
|
||||
// Check Permission
|
||||
if (!canView('hr_employees')) {
|
||||
@ -85,6 +86,12 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
// Fetch Departments for Dropdown
|
||||
$departments = db()->query("SELECT * FROM hr_departments ORDER BY name")->fetchAll();
|
||||
|
||||
// Pagination
|
||||
$page = $_GET['page'] ?? 1;
|
||||
$perPage = 10;
|
||||
$totalEmployees = db()->query("SELECT COUNT(*) FROM hr_employees")->fetchColumn();
|
||||
$pagination = getPagination($page, $totalEmployees, $perPage);
|
||||
|
||||
?>
|
||||
|
||||
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
|
||||
@ -224,7 +231,7 @@ $departments = db()->query("SELECT * FROM hr_departments ORDER BY name")->fetchA
|
||||
</div>
|
||||
|
||||
<!-- List View -->
|
||||
<div class="card shadow-sm">
|
||||
<div class="card shadow-sm mb-4">
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover align-middle">
|
||||
@ -240,8 +247,16 @@ $departments = db()->query("SELECT * FROM hr_departments ORDER BY name")->fetchA
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
$sql = "SELECT e.*, d.name as dept_name FROM hr_employees e LEFT JOIN hr_departments d ON e.department_id = d.id ORDER BY e.first_name";
|
||||
$stmt = db()->query($sql);
|
||||
$sql = "SELECT e.*, d.name as dept_name
|
||||
FROM hr_employees e
|
||||
LEFT JOIN hr_departments d ON e.department_id = d.id
|
||||
ORDER BY e.first_name
|
||||
LIMIT ? OFFSET ?";
|
||||
$stmt = db()->prepare($sql);
|
||||
$stmt->bindValue(1, $pagination['limit'], PDO::PARAM_INT);
|
||||
$stmt->bindValue(2, $pagination['offset'], PDO::PARAM_INT);
|
||||
$stmt->execute();
|
||||
|
||||
while ($row = $stmt->fetch()):
|
||||
?>
|
||||
<tr>
|
||||
@ -307,6 +322,9 @@ $departments = db()->query("SELECT * FROM hr_departments ORDER BY name")->fetchA
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer bg-white">
|
||||
<?= renderPagination($pagination['current_page'], $pagination['total_pages']) ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
|
||||
100
includes/pagination.php
Normal file
100
includes/pagination.php
Normal file
@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Calculate pagination parameters.
|
||||
*
|
||||
* @param int $page Current page number (1-based)
|
||||
* @param int $total Total number of items
|
||||
* @param int $perPage Items per page (default 10)
|
||||
* @return array ['offset' => int, 'limit' => int, 'total_pages' => int, 'current_page' => int]
|
||||
*/
|
||||
function getPagination($page, $total, $perPage = 10) {
|
||||
$page = max(1, (int)$page);
|
||||
$perPage = max(1, (int)$perPage);
|
||||
$totalPages = ceil($total / $perPage);
|
||||
|
||||
// Ensure page doesn't exceed total pages (unless total is 0)
|
||||
if ($totalPages > 0 && $page > $totalPages) {
|
||||
$page = $totalPages;
|
||||
}
|
||||
|
||||
$offset = ($page - 1) * $perPage;
|
||||
|
||||
return [
|
||||
'offset' => $offset,
|
||||
'limit' => $perPage,
|
||||
'total_pages' => $totalPages,
|
||||
'current_page' => $page
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to build pagination link with existing query params
|
||||
*/
|
||||
function getPaginationLink($page, $queryParams = []) {
|
||||
$params = array_merge($_GET, $queryParams);
|
||||
$params['page'] = $page;
|
||||
return '?' . http_build_query($params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render pagination links using Bootstrap 5.
|
||||
*
|
||||
* @param int $currentPage
|
||||
* @param int $totalPages
|
||||
* @return string HTML for pagination
|
||||
*/
|
||||
function renderPagination($currentPage, $totalPages) {
|
||||
if ($totalPages <= 1) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$html = '<nav aria-label="Page navigation" class="mt-4"><ul class="pagination justify-content-center">';
|
||||
|
||||
// Previous Button
|
||||
if ($currentPage > 1) {
|
||||
$html .= '<li class="page-item"><a class="page-link" href="' . getPaginationLink($currentPage - 1) . '">السابق</a></li>';
|
||||
} else {
|
||||
$html .= '<li class="page-item disabled"><span class="page-link">السابق</span></li>';
|
||||
}
|
||||
|
||||
// Page Numbers
|
||||
// Simple logic: Show all if <= 7, else show start, end, and around current
|
||||
// For simplicity in this iteration, let's show a sliding window or just simple list
|
||||
// Let's do a simple sliding window of 5
|
||||
$start = max(1, $currentPage - 2);
|
||||
$end = min($totalPages, $currentPage + 2);
|
||||
|
||||
if ($start > 1) {
|
||||
$html .= '<li class="page-item"><a class="page-link" href="' . getPaginationLink(1) . '">1</a></li>';
|
||||
if ($start > 2) {
|
||||
$html .= '<li class="page-item disabled"><span class="page-link">...</span></li>';
|
||||
}
|
||||
}
|
||||
|
||||
for ($i = $start; $i <= $end; $i++) {
|
||||
$active = ($i == $currentPage) ? 'active' : '';
|
||||
if ($i == $currentPage) {
|
||||
$html .= '<li class="page-item active"><span class="page-link">' . $i . '</span></li>';
|
||||
} else {
|
||||
$html .= '<li class="page-item"><a class="page-link" href="' . getPaginationLink($i) . '">' . $i . '</a></li>';
|
||||
}
|
||||
}
|
||||
|
||||
if ($end < $totalPages) {
|
||||
if ($end < $totalPages - 1) {
|
||||
$html .= '<li class="page-item disabled"><span class="page-link">...</span></li>';
|
||||
}
|
||||
$html .= '<li class="page-item"><a class="page-link" href="' . getPaginationLink($totalPages) . '">' . $totalPages . '</a></li>';
|
||||
}
|
||||
|
||||
// Next Button
|
||||
if ($currentPage < $totalPages) {
|
||||
$html .= '<li class="page-item"><a class="page-link" href="' . getPaginationLink($currentPage + 1) . '">التالي</a></li>';
|
||||
} else {
|
||||
$html .= '<li class="page-item disabled"><span class="page-link">التالي</span></li>';
|
||||
}
|
||||
|
||||
$html .= '</ul></nav>';
|
||||
return $html;
|
||||
}
|
||||
53
meetings.php
53
meetings.php
@ -1,6 +1,7 @@
|
||||
<?php
|
||||
ob_start();
|
||||
require_once __DIR__ . '/includes/header.php';
|
||||
require_once __DIR__ . '/includes/pagination.php';
|
||||
|
||||
if (!canView('meetings')) {
|
||||
redirect('index.php');
|
||||
@ -67,27 +68,60 @@ $date_to = $_GET['date_to'] ?? date('Y-m-t');
|
||||
$status_filter = $_GET['status'] ?? '';
|
||||
$search = $_GET['search'] ?? '';
|
||||
|
||||
$sql = "SELECT m.*, u.username as created_by_name
|
||||
FROM meetings m
|
||||
LEFT JOIN users u ON m.created_by = u.id
|
||||
WHERE DATE(m.start_time) BETWEEN ? AND ?";
|
||||
// Base WHERE conditions
|
||||
$whereConditions = ["DATE(m.start_time) BETWEEN ? AND ?"];
|
||||
$params = [$date_from, $date_to];
|
||||
|
||||
if ($status_filter) {
|
||||
$sql .= " AND m.status = ?";
|
||||
$whereConditions[] = "m.status = ?";
|
||||
$params[] = $status_filter;
|
||||
}
|
||||
if ($search) {
|
||||
$sql .= " AND (m.title LIKE ? OR m.description LIKE ? OR m.location LIKE ?)";
|
||||
$whereConditions[] = "(m.title LIKE ? OR m.description LIKE ? OR m.location LIKE ?)";
|
||||
$params[] = "%$search%";
|
||||
$params[] = "%$search%";
|
||||
$params[] = "%$search%";
|
||||
}
|
||||
|
||||
$sql .= " ORDER BY m.start_time ASC";
|
||||
$whereClause = implode(' AND ', $whereConditions);
|
||||
|
||||
// Pagination
|
||||
$page = $_GET['page'] ?? 1;
|
||||
$perPage = 10;
|
||||
|
||||
// Count Total Items
|
||||
$countSql = "SELECT COUNT(*) FROM meetings m WHERE $whereClause";
|
||||
$countStmt = db()->prepare($countSql);
|
||||
$countStmt->execute($params);
|
||||
$totalMeetings = $countStmt->fetchColumn();
|
||||
|
||||
$pagination = getPagination($page, $totalMeetings, $perPage);
|
||||
|
||||
// Fetch Items with Limit
|
||||
$sql = "SELECT m.*, u.username as created_by_name
|
||||
FROM meetings m
|
||||
LEFT JOIN users u ON m.created_by = u.id
|
||||
WHERE $whereClause
|
||||
ORDER BY m.start_time ASC
|
||||
LIMIT ? OFFSET ?";
|
||||
|
||||
// Add LIMIT and OFFSET to params
|
||||
$params[] = $pagination['limit'];
|
||||
$params[] = $pagination['offset'];
|
||||
|
||||
$stmt = db()->prepare($sql);
|
||||
$stmt->execute($params);
|
||||
|
||||
// Bind params manually because limit/offset must be integers
|
||||
// But wait, $params is mixed string/int.
|
||||
// PDO::execute($params) treats all as strings which is fine for limit/offset in MySQL usually,
|
||||
// but strictly speaking, LIMIT/OFFSET should be ints.
|
||||
// Let's bind all params.
|
||||
foreach ($params as $k => $v) {
|
||||
// 1-based index
|
||||
$type = is_int($v) ? PDO::PARAM_INT : PDO::PARAM_STR;
|
||||
$stmt->bindValue($k + 1, $v, $type);
|
||||
}
|
||||
$stmt->execute();
|
||||
$meetings = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
if (isset($_SESSION['success'])) {
|
||||
@ -244,6 +278,9 @@ if (isset($_SESSION['success'])) {
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer bg-white">
|
||||
<?= renderPagination($pagination['current_page'], $pagination['total_pages']) ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal -->
|
||||
|
||||
15
users.php
15
users.php
@ -1,5 +1,6 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/includes/header.php';
|
||||
require_once __DIR__ . '/includes/pagination.php';
|
||||
|
||||
if (!canView('users')) {
|
||||
redirect('index.php');
|
||||
@ -174,7 +175,16 @@ if (isset($_SESSION['error'])) {
|
||||
unset($_SESSION['error']);
|
||||
}
|
||||
|
||||
$stmt = db()->query("SELECT * FROM users ORDER BY created_at DESC");
|
||||
// Pagination
|
||||
$page = $_GET['page'] ?? 1;
|
||||
$perPage = 10;
|
||||
$totalUsers = db()->query("SELECT COUNT(*) FROM users")->fetchColumn();
|
||||
$pagination = getPagination($page, $totalUsers, $perPage);
|
||||
|
||||
$stmt = db()->prepare("SELECT * FROM users ORDER BY created_at DESC LIMIT ? OFFSET ?");
|
||||
$stmt->bindValue(1, $pagination['limit'], PDO::PARAM_INT);
|
||||
$stmt->bindValue(2, $pagination['offset'], PDO::PARAM_INT);
|
||||
$stmt->execute();
|
||||
$users = $stmt->fetchAll();
|
||||
|
||||
// Fetch permissions for all users
|
||||
@ -278,6 +288,9 @@ if (isset($_GET['action']) && $_GET['action'] === 'edit' && isset($_GET['id']))
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer bg-white">
|
||||
<?= renderPagination($pagination['current_page'], $pagination['total_pages']) ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- User Modal -->
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user