Paginate registration lists

This commit is contained in:
Cauê Faleiros
2026-08-10 10:36:41 -03:00
parent 14fe69bb9d
commit b059ea3128

View File

@@ -11,11 +11,13 @@ import {
saveCatalogProduct, saveCatalogProduct,
saveConsumptionReference saveConsumptionReference
} from '../dataService'; } from '../dataService';
import PaginationControls from '../components/PaginationControls';
import type { CatalogCategory, CatalogProduct, CatalogProductType, CatalogSummary, ConsumptionReference } from '../types'; import type { CatalogCategory, CatalogProduct, CatalogProductType, CatalogSummary, ConsumptionReference } from '../types';
import { formatColorLabel } from '../displayFormatters'; import { formatColorLabel } from '../displayFormatters';
type RegistrationTab = 'products' | 'categories' | 'references'; type RegistrationTab = 'products' | 'categories' | 'references';
type SaveStatus = 'idle' | 'saving' | 'saved' | 'error'; type SaveStatus = 'idle' | 'saving' | 'saved' | 'error';
type RegistrationPagination = Record<RegistrationTab, { page: number; pageSize: number }>;
const emptyCatalog: CatalogSummary = { const emptyCatalog: CatalogSummary = {
categories: [], categories: [],
@@ -111,6 +113,11 @@ const Registrations = () => {
const [isLoading, setIsLoading] = useState(true); const [isLoading, setIsLoading] = useState(true);
const [activeTab, setActiveTab] = useState<RegistrationTab>('products'); const [activeTab, setActiveTab] = useState<RegistrationTab>('products');
const [productFilter, setProductFilter] = useState<'all' | CatalogProductType>('all'); const [productFilter, setProductFilter] = useState<'all' | CatalogProductType>('all');
const [pagination, setPagination] = useState<RegistrationPagination>({
products: { page: 1, pageSize: 20 },
categories: { page: 1, pageSize: 20 },
references: { page: 1, pageSize: 20 },
});
const [status, setStatus] = useState<SaveStatus>('idle'); const [status, setStatus] = useState<SaveStatus>('idle');
const [feedback, setFeedback] = useState(''); const [feedback, setFeedback] = useState('');
const appliedSkuPrefillRef = useRef(''); const appliedSkuPrefillRef = useRef('');
@@ -247,6 +254,28 @@ const Registrations = () => {
return catalog.products.filter(product => product.type === productFilter); return catalog.products.filter(product => product.type === productFilter);
}, [catalog.products, productFilter]); }, [catalog.products, productFilter]);
const updatePagination = (tab: RegistrationTab, patch: Partial<RegistrationPagination[RegistrationTab]>) => {
setPagination(current => ({
...current,
[tab]: { ...current[tab], ...patch }
}));
};
const productTotalPages = Math.ceil(filteredProducts.length / pagination.products.pageSize);
const safeProductPage = Math.min(pagination.products.page, productTotalPages || 1);
const productStartIndex = (safeProductPage - 1) * pagination.products.pageSize;
const paginatedProducts = filteredProducts.slice(productStartIndex, productStartIndex + pagination.products.pageSize);
const categoryTotalPages = Math.ceil(catalog.categories.length / pagination.categories.pageSize);
const safeCategoryPage = Math.min(pagination.categories.page, categoryTotalPages || 1);
const categoryStartIndex = (safeCategoryPage - 1) * pagination.categories.pageSize;
const paginatedCategories = catalog.categories.slice(categoryStartIndex, categoryStartIndex + pagination.categories.pageSize);
const referenceTotalPages = Math.ceil(catalog.consumptionReferences.length / pagination.references.pageSize);
const safeReferencePage = Math.min(pagination.references.page, referenceTotalPages || 1);
const referenceStartIndex = (safeReferencePage - 1) * pagination.references.pageSize;
const paginatedReferences = catalog.consumptionReferences.slice(referenceStartIndex, referenceStartIndex + pagination.references.pageSize);
const runAction = async (action: () => Promise<void>, successMessage: string) => { const runAction = async (action: () => Promise<void>, successMessage: string) => {
setStatus('saving'); setStatus('saving');
setFeedback(''); setFeedback('');
@@ -473,7 +502,10 @@ const Registrations = () => {
</div> </div>
<select <select
value={productFilter} value={productFilter}
onChange={(event) => setProductFilter(event.target.value as 'all' | CatalogProductType)} onChange={(event) => {
setProductFilter(event.target.value as 'all' | CatalogProductType);
updatePagination('products', { page: 1 });
}}
className="h-10 rounded-xl border border-dark-border bg-dark-input px-3 text-sm font-bold text-dark-text outline-none focus:border-brand-primary cursor-pointer" className="h-10 rounded-xl border border-dark-border bg-dark-input px-3 text-sm font-bold text-dark-text outline-none focus:border-brand-primary cursor-pointer"
> >
<option value="all">Todos</option> <option value="all">Todos</option>
@@ -482,7 +514,7 @@ const Registrations = () => {
</select> </select>
</div> </div>
<div className="divide-y divide-dark-border"> <div className="divide-y divide-dark-border">
{filteredProducts.map(product => ( {paginatedProducts.map(product => (
<div key={product.id} className="flex flex-col gap-3 p-4 md:flex-row md:items-center md:justify-between"> <div key={product.id} className="flex flex-col gap-3 p-4 md:flex-row md:items-center md:justify-between">
<div className="min-w-0"> <div className="min-w-0">
<div className="flex flex-wrap items-center gap-2"> <div className="flex flex-wrap items-center gap-2">
@@ -512,6 +544,19 @@ const Registrations = () => {
<div className={emptyStateClassName}>Nenhum produto cadastrado.</div> <div className={emptyStateClassName}>Nenhum produto cadastrado.</div>
)} )}
</div> </div>
<PaginationControls
totalItems={filteredProducts.length}
currentPage={safeProductPage}
totalPages={productTotalPages}
pageSize={pagination.products.pageSize}
pageSizeOptions={[10, 20, 50, 100]}
itemLabel="produtos"
pageSizeLabel="por página"
startIndex={productStartIndex}
endIndex={Math.min(productStartIndex + pagination.products.pageSize, filteredProducts.length)}
onPageChange={(page) => updatePagination('products', { page })}
onPageSizeChange={(pageSize) => updatePagination('products', { page: 1, pageSize })}
/>
</div> </div>
<div className={formPanelClassName}> <div className={formPanelClassName}>
@@ -662,7 +707,7 @@ const Registrations = () => {
</div> </div>
</div> </div>
<div className="divide-y divide-dark-border"> <div className="divide-y divide-dark-border">
{catalog.categories.map(category => ( {paginatedCategories.map(category => (
<div key={category.id} className="flex items-center justify-between gap-3 p-4"> <div key={category.id} className="flex items-center justify-between gap-3 p-4">
<div> <div>
<h3 className="text-sm font-bold text-dark-text">{category.name}</h3> <h3 className="text-sm font-bold text-dark-text">{category.name}</h3>
@@ -675,6 +720,19 @@ const Registrations = () => {
))} ))}
{!catalog.categories.length && <div className={emptyStateClassName}>Nenhuma categoria cadastrada.</div>} {!catalog.categories.length && <div className={emptyStateClassName}>Nenhuma categoria cadastrada.</div>}
</div> </div>
<PaginationControls
totalItems={catalog.categories.length}
currentPage={safeCategoryPage}
totalPages={categoryTotalPages}
pageSize={pagination.categories.pageSize}
pageSizeOptions={[10, 20, 50, 100]}
itemLabel="categorias"
pageSizeLabel="por página"
startIndex={categoryStartIndex}
endIndex={Math.min(categoryStartIndex + pagination.categories.pageSize, catalog.categories.length)}
onPageChange={(page) => updatePagination('categories', { page })}
onPageSizeChange={(pageSize) => updatePagination('categories', { page: 1, pageSize })}
/>
</div> </div>
<div className={formPanelClassName}> <div className={formPanelClassName}>
@@ -710,7 +768,7 @@ const Registrations = () => {
</span> </span>
</div> </div>
<div className="divide-y divide-dark-border"> <div className="divide-y divide-dark-border">
{catalog.consumptionReferences.map(reference => ( {paginatedReferences.map(reference => (
<div key={reference.id} className="flex flex-col gap-3 p-4 md:flex-row md:items-start md:justify-between"> <div key={reference.id} className="flex flex-col gap-3 p-4 md:flex-row md:items-start md:justify-between">
<div className="min-w-0"> <div className="min-w-0">
<div className="flex flex-wrap items-center gap-2"> <div className="flex flex-wrap items-center gap-2">
@@ -768,6 +826,19 @@ const Registrations = () => {
</div> </div>
)} )}
</div> </div>
<PaginationControls
totalItems={catalog.consumptionReferences.length}
currentPage={safeReferencePage}
totalPages={referenceTotalPages}
pageSize={pagination.references.pageSize}
pageSizeOptions={[10, 20, 50, 100]}
itemLabel="referências"
pageSizeLabel="por página"
startIndex={referenceStartIndex}
endIndex={Math.min(referenceStartIndex + pagination.references.pageSize, catalog.consumptionReferences.length)}
onPageChange={(page) => updatePagination('references', { page })}
onPageSizeChange={(pageSize) => updatePagination('references', { page: 1, pageSize })}
/>
</div> </div>
<div className={formPanelClassName}> <div className={formPanelClassName}>