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:
@@ -169,12 +169,7 @@ function handleGetStats(PDO $pdo): void
|
||||
|
||||
function handleGetList(PDO $pdo): void
|
||||
{
|
||||
$search = trim($_GET['search'] ?? '');
|
||||
$statusFilter = trim($_GET['status'] ?? '');
|
||||
$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 = [
|
||||
'InvoiceNumber' => 'i.invoice_number',
|
||||
@@ -188,10 +183,8 @@ function handleGetList(PDO $pdo): void
|
||||
'IssueDate' => 'i.issue_date',
|
||||
'issue_date' => 'i.issue_date',
|
||||
];
|
||||
if (!isset($sortMap[$sort])) {
|
||||
errorResponse('Neplatný parametr řazení', 400);
|
||||
}
|
||||
$sortCol = $sortMap[$sort];
|
||||
|
||||
$p = PaginationHelper::parseParams($sortMap);
|
||||
|
||||
// Lazy overdue detekce
|
||||
$pdo->exec("UPDATE invoices SET status = 'overdue' WHERE status = 'issued' AND due_date < CURDATE()");
|
||||
@@ -199,10 +192,9 @@ function handleGetList(PDO $pdo): void
|
||||
$where = 'WHERE 1=1';
|
||||
$params = [];
|
||||
|
||||
if ($search) {
|
||||
$search = mb_substr($search, 0, 100);
|
||||
if ($p['search']) {
|
||||
$where .= ' AND (i.invoice_number LIKE ? OR c.name LIKE ? OR c.company_id LIKE ?)';
|
||||
$searchParam = "%{$search}%";
|
||||
$searchParam = "%{$p['search']}%";
|
||||
$params = array_merge($params, [$searchParam, $searchParam, $searchParam]);
|
||||
}
|
||||
|
||||
@@ -215,36 +207,26 @@ function handleGetList(PDO $pdo): void
|
||||
}
|
||||
}
|
||||
|
||||
$countSql = "
|
||||
SELECT COUNT(*)
|
||||
FROM invoices i
|
||||
$from = "FROM invoices i
|
||||
LEFT JOIN customers c ON i.customer_id = c.id
|
||||
$where
|
||||
";
|
||||
$stmt = $pdo->prepare($countSql);
|
||||
$stmt->execute($params);
|
||||
$total = (int) $stmt->fetchColumn();
|
||||
LEFT JOIN orders o ON i.order_id = o.id";
|
||||
|
||||
$offset = ($page - 1) * $perPage;
|
||||
|
||||
$sql = "
|
||||
SELECT i.id, i.invoice_number, i.order_id, i.status, i.currency,
|
||||
$result = PaginationHelper::paginate(
|
||||
$pdo,
|
||||
"SELECT COUNT(*) FROM invoices i LEFT JOIN customers c ON i.customer_id = c.id {$where}",
|
||||
"SELECT i.id, i.invoice_number, i.order_id, i.status, i.currency,
|
||||
i.issue_date, i.due_date, i.paid_date, i.created_at, i.apply_vat,
|
||||
c.name as customer_name,
|
||||
(SELECT COALESCE(SUM(ii.quantity * ii.unit_price), 0)
|
||||
FROM invoice_items ii WHERE ii.invoice_id = i.id) as subtotal,
|
||||
o.order_number
|
||||
FROM invoices i
|
||||
LEFT JOIN customers c ON i.customer_id = c.id
|
||||
LEFT JOIN orders o ON i.order_id = o.id
|
||||
$where
|
||||
ORDER BY $sortCol $order
|
||||
LIMIT $perPage OFFSET $offset
|
||||
";
|
||||
{$from} {$where}
|
||||
ORDER BY {$p['sort']} {$p['order']}",
|
||||
$params,
|
||||
$p
|
||||
);
|
||||
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute($params);
|
||||
$invoices = $stmt->fetchAll();
|
||||
$invoices = $result['items'];
|
||||
|
||||
// Dopocitat celkovou castku s DPH
|
||||
foreach ($invoices as &$inv) {
|
||||
@@ -265,9 +247,7 @@ function handleGetList(PDO $pdo): void
|
||||
|
||||
successResponse([
|
||||
'invoices' => $invoices,
|
||||
'total' => $total,
|
||||
'page' => $page,
|
||||
'per_page' => $perPage,
|
||||
'pagination' => $result['pagination'],
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
@@ -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'],
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
@@ -25,12 +25,6 @@ function generateOrderNumber(PDO $pdo): string
|
||||
|
||||
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 = [
|
||||
'OrderNumber' => 'o.order_number',
|
||||
'order_number' => 'o.order_number',
|
||||
@@ -41,36 +35,25 @@ function handleGetList(PDO $pdo): void
|
||||
'Currency' => 'o.currency',
|
||||
'currency' => 'o.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 (o.order_number LIKE ? OR q.quotation_number LIKE ? OR q.project_code LIKE ? OR c.name LIKE ?)';
|
||||
$searchParam = "%{$search}%";
|
||||
$searchParam = "%{$p['search']}%";
|
||||
$params = [$searchParam, $searchParam, $searchParam, $searchParam];
|
||||
}
|
||||
|
||||
$countSql = "
|
||||
SELECT COUNT(*)
|
||||
FROM orders o
|
||||
$from = "FROM orders o
|
||||
LEFT JOIN quotations q ON o.quotation_id = q.id
|
||||
LEFT JOIN customers c ON o.customer_id = c.id
|
||||
$where
|
||||
";
|
||||
$stmt = $pdo->prepare($countSql);
|
||||
$stmt->execute($params);
|
||||
$total = (int) $stmt->fetchColumn();
|
||||
LEFT JOIN customers c ON o.customer_id = c.id";
|
||||
|
||||
$offset = ($page - 1) * $perPage;
|
||||
|
||||
$sql = "
|
||||
SELECT o.id, o.order_number, o.quotation_id, o.status, o.currency,
|
||||
$result = PaginationHelper::paginate(
|
||||
$pdo,
|
||||
"SELECT COUNT(*) {$from} {$where}",
|
||||
"SELECT o.id, o.order_number, o.quotation_id, o.status, o.currency,
|
||||
o.created_at, o.apply_vat, o.vat_rate,
|
||||
q.quotation_number, q.project_code,
|
||||
c.name as customer_name,
|
||||
@@ -78,23 +61,15 @@ function handleGetList(PDO $pdo): void
|
||||
FROM order_items oi WHERE oi.order_id = o.id) as total,
|
||||
(SELECT inv.id FROM invoices inv WHERE inv.order_id = o.id LIMIT 1) as invoice_id,
|
||||
(SELECT inv.invoice_number FROM invoices inv WHERE inv.order_id = o.id LIMIT 1) as invoice_number
|
||||
FROM orders o
|
||||
LEFT JOIN quotations q ON o.quotation_id = q.id
|
||||
LEFT JOIN customers c ON o.customer_id = c.id
|
||||
$where
|
||||
ORDER BY $sortCol $order
|
||||
LIMIT $perPage OFFSET $offset
|
||||
";
|
||||
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute($params);
|
||||
$orders = $stmt->fetchAll();
|
||||
{$from} {$where}
|
||||
ORDER BY {$p['sort']} {$p['order']}",
|
||||
$params,
|
||||
$p
|
||||
);
|
||||
|
||||
successResponse([
|
||||
'orders' => $orders,
|
||||
'total' => $total,
|
||||
'page' => $page,
|
||||
'per_page' => $perPage,
|
||||
'orders' => $result['items'],
|
||||
'pagination' => $result['pagination'],
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
@@ -156,12 +156,6 @@ function handleDeleteProject(PDO $pdo, int $id): void
|
||||
|
||||
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 = [
|
||||
'ProjectNumber' => 'p.project_number',
|
||||
'project_number' => 'p.project_number',
|
||||
@@ -176,56 +170,37 @@ function handleGetList(PDO $pdo): void
|
||||
'CreatedAt' => 'p.created_at',
|
||||
'created_at' => 'p.created_at',
|
||||
];
|
||||
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 (p.project_number LIKE ? OR p.name LIKE ? OR c.name LIKE ?)';
|
||||
$searchParam = "%{$search}%";
|
||||
$searchParam = "%{$p['search']}%";
|
||||
$params = [$searchParam, $searchParam, $searchParam];
|
||||
}
|
||||
|
||||
$countSql = "
|
||||
SELECT COUNT(*)
|
||||
FROM projects p
|
||||
$from = "FROM projects p
|
||||
LEFT JOIN customers c ON p.customer_id = c.id
|
||||
LEFT JOIN orders o ON p.order_id = o.id
|
||||
$where
|
||||
";
|
||||
$stmt = $pdo->prepare($countSql);
|
||||
$stmt->execute($params);
|
||||
$total = (int) $stmt->fetchColumn();
|
||||
LEFT JOIN orders o ON p.order_id = o.id";
|
||||
|
||||
$offset = ($page - 1) * $perPage;
|
||||
|
||||
$sql = "
|
||||
SELECT p.id, p.project_number, p.name, p.status, p.start_date, p.end_date,
|
||||
$result = PaginationHelper::paginate(
|
||||
$pdo,
|
||||
"SELECT COUNT(*) {$from} {$where}",
|
||||
"SELECT p.id, p.project_number, p.name, p.status, p.start_date, p.end_date,
|
||||
p.order_id, p.quotation_id, p.created_at,
|
||||
c.name as customer_name,
|
||||
o.order_number
|
||||
FROM projects p
|
||||
LEFT JOIN customers c ON p.customer_id = c.id
|
||||
LEFT JOIN orders o ON p.order_id = o.id
|
||||
$where
|
||||
ORDER BY $sortCol $order
|
||||
LIMIT $perPage OFFSET $offset
|
||||
";
|
||||
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute($params);
|
||||
$projects = $stmt->fetchAll();
|
||||
{$from} {$where}
|
||||
ORDER BY {$p['sort']} {$p['order']}",
|
||||
$params,
|
||||
$p
|
||||
);
|
||||
|
||||
successResponse([
|
||||
'projects' => $projects,
|
||||
'total' => $total,
|
||||
'page' => $page,
|
||||
'per_page' => $perPage,
|
||||
'projects' => $result['items'],
|
||||
'pagination' => $result['pagination'],
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user