mirror of
https://github.com/christianvidalwolf-prog/Craze-Data-check.git
synced 2026-08-03 11:55:23 +02:00
Add pagination to Pricing tab
Load data in batches of 100 products per page with navigation controls
This commit is contained in:
@@ -51,6 +51,8 @@ export function PricingView({ data, headers, onSaveRow, onCaptureState, onEdit,
|
||||
const [filterMode, setFilterMode] = useState<FilterMode>('all_errors');
|
||||
const [search, setSearch] = useState('');
|
||||
const [searchMode, setSearchMode] = useState<'all' | 'selected'>('all');
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const pageSize = 100;
|
||||
const [columnWidths, setColumnWidths] = useState<Record<string, number>>({
|
||||
articleNo: 100,
|
||||
articleName: 220,
|
||||
@@ -387,6 +389,14 @@ export function PricingView({ data, headers, onSaveRow, onCaptureState, onEdit,
|
||||
return sorted;
|
||||
}, [filteredRows, sortConfig]);
|
||||
|
||||
// ── Pagination ─────────────────────────────────────────────────────────
|
||||
const paginatedRows = useMemo(() => {
|
||||
const start = (currentPage - 1) * pageSize;
|
||||
return sortedRows.slice(start, start + pageSize);
|
||||
}, [sortedRows, currentPage]);
|
||||
|
||||
const totalPages = Math.ceil(sortedRows.length / pageSize);
|
||||
|
||||
const handleSort = (key: string | number) => {
|
||||
setSortConfig(prev => {
|
||||
if (prev.key === key) {
|
||||
@@ -713,7 +723,7 @@ export function PricingView({ data, headers, onSaveRow, onCaptureState, onEdit,
|
||||
{FILTERS.map(f => (
|
||||
<button
|
||||
key={f.id}
|
||||
onClick={() => setFilterMode(f.id)}
|
||||
onClick={() => { setFilterMode(f.id); setCurrentPage(1); }}
|
||||
className={cn(
|
||||
'flex items-center gap-2 px-3 py-1.5 rounded-md text-sm font-medium transition-colors',
|
||||
filterMode === f.id
|
||||
@@ -1056,7 +1066,7 @@ export function PricingView({ data, headers, onSaveRow, onCaptureState, onEdit,
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{sortedRows.map(({ row, dataIndex, pricingErrors, unitErrors, isCritical }) => {
|
||||
{paginatedRows.map(({ row, dataIndex, pricingErrors, unitErrors, isCritical }) => {
|
||||
const saveStatus = rowStatuses[String(row[COLUMNS.ARTICLE_NO])];
|
||||
const isValidated = !!row[COLUMNS.VALIDATED_CHECK];
|
||||
const note = String(row[COLUMNS.VALIDATED_NOTE] || '');
|
||||
@@ -1274,13 +1284,50 @@ export function PricingView({ data, headers, onSaveRow, onCaptureState, onEdit,
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* ── Footer count ── */}
|
||||
<p className="text-xs text-slate-500 pb-1">
|
||||
Showing {filteredRows.length} of {stats.total} products
|
||||
{pricingEditableCols.length > 0 && (
|
||||
<> · Click any <span className="text-blue-400">price cell</span> to edit inline</>
|
||||
{/* ── Footer count & Pagination ── */}
|
||||
<div className="flex items-center justify-between">
|
||||
<p className="text-xs text-slate-500 pb-1">
|
||||
Showing {paginatedRows.length} of {sortedRows.length} products {totalPages > 1 && `(${currentPage}/${totalPages})`}
|
||||
{pricingEditableCols.length > 0 && (
|
||||
<> · Click any <span className="text-blue-400">price cell</span> to edit inline</>
|
||||
)}
|
||||
</p>
|
||||
{totalPages > 1 && (
|
||||
<div className="flex items-center gap-1">
|
||||
<button
|
||||
onClick={() => setCurrentPage(1)}
|
||||
disabled={currentPage === 1}
|
||||
className="px-2 py-1 text-xs bg-slate-800 hover:bg-slate-700 rounded disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
>
|
||||
««
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setCurrentPage(p => Math.max(1, p - 1))}
|
||||
disabled={currentPage === 1}
|
||||
className="px-2 py-1 text-xs bg-slate-800 hover:bg-slate-700 rounded disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
>
|
||||
«
|
||||
</button>
|
||||
<span className="text-xs text-slate-400 px-2">
|
||||
{currentPage} / {totalPages}
|
||||
</span>
|
||||
<button
|
||||
onClick={() => setCurrentPage(p => Math.min(totalPages, p + 1))}
|
||||
disabled={currentPage === totalPages}
|
||||
className="px-2 py-1 text-xs bg-slate-800 hover:bg-slate-700 rounded disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
>
|
||||
»
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setCurrentPage(totalPages)}
|
||||
disabled={currentPage === totalPages}
|
||||
className="px-2 py-1 text-xs bg-slate-800 hover:bg-slate-700 rounded disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
>
|
||||
»»
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user