feat: P2 strankovani - PaginationHelper, Pagination komponenta, integrace do 4 modulu
- PaginationHelper.php: parseParams() + paginate() - DRY backend pagination logika - Pagination.jsx: frontend strankovaci komponenta (prev/next/cisla/info) - CSS: .admin-pagination styly v admin.css - Refaktor handleru: offers, orders, invoices, projects pouzivaji PaginationHelper - Default 25 zaznamu na stranku (misto 500), max 500 - Frontend: page state + reset na search/filter zmenu - useListData: pagination data v response Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
82
api/includes/PaginationHelper.php
Normal file
82
api/includes/PaginationHelper.php
Normal file
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Pagination helper - extrakce spolecne logiky pro strankovani seznamu.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
class PaginationHelper
|
||||
{
|
||||
private const DEFAULT_PER_PAGE = 25;
|
||||
private const MAX_PER_PAGE = 500;
|
||||
|
||||
/**
|
||||
* Nacte pagination parametry z GET requestu.
|
||||
*
|
||||
* @return array{page: int, per_page: int, sort: string, order: string, search: string}
|
||||
*/
|
||||
public static function parseParams(array $sortMap, string $defaultSort = 'created_at'): array
|
||||
{
|
||||
$sort = $_GET['sort'] ?? $defaultSort;
|
||||
$order = strtoupper($_GET['order'] ?? 'DESC') === 'ASC' ? 'ASC' : 'DESC';
|
||||
$page = max(1, (int) ($_GET['page'] ?? 1));
|
||||
$perPage = min(self::MAX_PER_PAGE, max(1, (int) ($_GET['per_page'] ?? self::DEFAULT_PER_PAGE)));
|
||||
$search = trim($_GET['search'] ?? '');
|
||||
|
||||
if (!isset($sortMap[$sort])) {
|
||||
errorResponse('Neplatný parametr řazení', 400);
|
||||
}
|
||||
|
||||
return [
|
||||
'page' => $page,
|
||||
'per_page' => $perPage,
|
||||
'sort' => $sortMap[$sort],
|
||||
'order' => $order,
|
||||
'search' => $search ? mb_substr($search, 0, 100) : '',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Spusti COUNT + SELECT dotazy s pagination a vrati vysledek.
|
||||
*
|
||||
* @param PDO $pdo
|
||||
* @param string $countSql - COUNT(*) dotaz
|
||||
* @param string $dataSql - SELECT dotaz (bez LIMIT/OFFSET)
|
||||
* @param array $params - parametry pro prepared statement
|
||||
* @param array{page: int, per_page: int, sort: string, order: string} $pagination
|
||||
* @return array{items: array, pagination: array}
|
||||
*/
|
||||
public static function paginate(
|
||||
PDO $pdo,
|
||||
string $countSql,
|
||||
string $dataSql,
|
||||
array $params,
|
||||
array $pagination
|
||||
): array {
|
||||
$page = $pagination['page'];
|
||||
$perPage = $pagination['per_page'];
|
||||
|
||||
$stmt = $pdo->prepare($countSql);
|
||||
$stmt->execute($params);
|
||||
$total = (int) $stmt->fetchColumn();
|
||||
|
||||
$offset = ($page - 1) * $perPage;
|
||||
$totalPages = (int) ceil($total / $perPage);
|
||||
|
||||
$sql = "{$dataSql} LIMIT {$perPage} OFFSET {$offset}";
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute($params);
|
||||
$items = $stmt->fetchAll();
|
||||
|
||||
return [
|
||||
'items' => $items,
|
||||
'pagination' => [
|
||||
'total' => $total,
|
||||
'page' => $page,
|
||||
'per_page' => $perPage,
|
||||
'total_pages' => $totalPages,
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user