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:
2026-03-12 18:07:29 +01:00
parent 6ad20ea04e
commit 6863c7c557
15 changed files with 372 additions and 177 deletions

View File

@@ -4,12 +4,6 @@ declare(strict_types=1);
function handleGetList(PDO $pdo): void
{
$search = trim($_GET['search'] ?? '');
$sort = $_GET['sort'] ?? 'created_at';
$order = strtoupper($_GET['order'] ?? 'DESC') === 'ASC' ? 'ASC' : 'DESC';
$page = max(1, (int) ($_GET['page'] ?? 1));
$perPage = min(500, max(1, (int) ($_GET['per_page'] ?? 500)));
$sortMap = [
'Date' => 'q.created_at',
'CreatedAt' => 'q.created_at',
@@ -23,57 +17,37 @@ function handleGetList(PDO $pdo): void
'Currency' => 'q.currency',
'currency' => 'q.currency',
];
if (!isset($sortMap[$sort])) {
errorResponse('Neplatný parametr řazení', 400);
}
$sortCol = $sortMap[$sort];
$p = PaginationHelper::parseParams($sortMap);
$where = 'WHERE 1=1';
$params = [];
if ($search) {
$search = mb_substr($search, 0, 100);
if ($p['search']) {
$where .= ' AND (q.quotation_number LIKE ? OR q.project_code LIKE ? OR c.name LIKE ?)';
$searchParam = "%{$search}%";
$searchParam = "%{$p['search']}%";
$params = [$searchParam, $searchParam, $searchParam];
}
// Celkovy pocet pro pagination
$countSql = "
SELECT COUNT(*)
FROM quotations q
LEFT JOIN customers c ON q.customer_id = c.id
$where
";
$stmt = $pdo->prepare($countSql);
$stmt->execute($params);
$total = (int) $stmt->fetchColumn();
$from = "FROM quotations q LEFT JOIN customers c ON q.customer_id = c.id";
$offset = ($page - 1) * $perPage;
$sql = "
SELECT q.id, q.quotation_number, q.project_code, q.created_at, q.valid_until,
$result = PaginationHelper::paginate(
$pdo,
"SELECT COUNT(*) {$from} {$where}",
"SELECT q.id, q.quotation_number, q.project_code, q.created_at, q.valid_until,
q.currency, q.language, q.apply_vat, q.vat_rate, q.exchange_rate,
q.customer_id, q.order_id, q.status,
c.name as customer_name,
(SELECT COALESCE(SUM(CASE WHEN qi.is_included_in_total THEN qi.quantity * qi.unit_price ELSE 0 END), 0)
FROM quotation_items qi WHERE qi.quotation_id = q.id) as total
FROM quotations q
LEFT JOIN customers c ON q.customer_id = c.id
$where
ORDER BY $sortCol $order
LIMIT $perPage OFFSET $offset
";
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
$quotations = $stmt->fetchAll();
{$from} {$where}
ORDER BY {$p['sort']} {$p['order']}",
$params,
$p
);
successResponse([
'quotations' => $quotations,
'total' => $total,
'page' => $page,
'per_page' => $perPage,
'quotations' => $result['items'],
'pagination' => $result['pagination'],
]);
}