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:
@@ -11,6 +11,7 @@ import { formatCurrency, formatDate, czechPlural } from '../utils/formatters'
|
||||
import SortIcon from '../components/SortIcon'
|
||||
import useTableSort from '../hooks/useTableSort'
|
||||
import useListData from '../hooks/useListData'
|
||||
import Pagination from '../components/Pagination'
|
||||
|
||||
const ReceivedInvoices = lazy(() => import('./ReceivedInvoices'))
|
||||
const API_BASE = '/api/admin'
|
||||
@@ -65,6 +66,7 @@ export default function Invoices() {
|
||||
const [receivedUploadOpen, setReceivedUploadOpen] = useState(false)
|
||||
const { sort, order, handleSort, activeSort } = useTableSort('invoice_number')
|
||||
const [search, setSearch] = useState('')
|
||||
const [page, setPage] = useState(1)
|
||||
const [statusFilter, setStatusFilter] = useState('')
|
||||
|
||||
const now = new Date()
|
||||
@@ -139,8 +141,8 @@ export default function Invoices() {
|
||||
setDraft(null)
|
||||
}
|
||||
|
||||
const { items: invoices, loading, refetch: fetchData } = useListData('invoices.php', {
|
||||
dataKey: 'invoices', search, sort, order,
|
||||
const { items: invoices, loading, pagination, refetch: fetchData } = useListData('invoices.php', {
|
||||
dataKey: 'invoices', search, sort, order, page,
|
||||
extraParams: statusFilter ? { status: statusFilter } : {},
|
||||
errorMsg: 'Nepodařilo se načíst faktury'
|
||||
})
|
||||
@@ -269,7 +271,7 @@ export default function Invoices() {
|
||||
<div>
|
||||
<h1 className="admin-page-title">Faktury</h1>
|
||||
<p className="admin-page-subtitle">
|
||||
{invoices.length} {czechPlural(invoices.length, 'faktura', 'faktury', 'faktur')}
|
||||
{pagination?.total ?? invoices.length} {czechPlural(pagination?.total ?? invoices.length, 'faktura', 'faktury', 'faktur')}
|
||||
</p>
|
||||
</div>
|
||||
{hasPermission('invoices.create') && (
|
||||
@@ -430,7 +432,7 @@ export default function Invoices() {
|
||||
<button
|
||||
key={f.value}
|
||||
className={`offers-tab ${statusFilter === f.value ? 'active' : ''}`}
|
||||
onClick={() => setStatusFilter(f.value)}
|
||||
onClick={() => { setStatusFilter(f.value); setPage(1) }}
|
||||
>
|
||||
{f.label}
|
||||
</button>
|
||||
@@ -450,7 +452,7 @@ export default function Invoices() {
|
||||
<input
|
||||
type="text"
|
||||
value={search}
|
||||
onChange={(e) => setSearch(e.target.value)}
|
||||
onChange={(e) => { setSearch(e.target.value); setPage(1) }}
|
||||
className="admin-form-input"
|
||||
placeholder="Hledat podle čísla faktury, zákazníka nebo IČ..."
|
||||
/>
|
||||
@@ -622,6 +624,7 @@ export default function Invoices() {
|
||||
</table>
|
||||
</div>
|
||||
)}
|
||||
<Pagination pagination={pagination} onPageChange={setPage} />
|
||||
</div>
|
||||
</motion.div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user