Paginate product variations
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 1m0s
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 1m0s
This commit is contained in:
@@ -7,6 +7,7 @@ import DateRangePicker from '../components/DateRangePicker';
|
|||||||
import SkuPlanningModal from '../components/SkuPlanningModal';
|
import SkuPlanningModal from '../components/SkuPlanningModal';
|
||||||
import ProductTypeBadge from '../components/ProductTypeBadge';
|
import ProductTypeBadge from '../components/ProductTypeBadge';
|
||||||
import RefreshStatus from '../components/RefreshStatus';
|
import RefreshStatus from '../components/RefreshStatus';
|
||||||
|
import PaginationControls from '../components/PaginationControls';
|
||||||
import type { CutProductOverride, CuttingSettings, DateRange, ProductComposition, ProductDetailsAnalytics } from '../types';
|
import type { CutProductOverride, CuttingSettings, DateRange, ProductComposition, ProductDetailsAnalytics } from '../types';
|
||||||
import { fetchCuttingSettings, fetchProductComposition, fetchProductDetailsAnalytics, saveCuttingSettings } from '../dataService';
|
import { fetchCuttingSettings, fetchProductComposition, fetchProductDetailsAnalytics, saveCuttingSettings } from '../dataService';
|
||||||
import { parseProductName } from '../productParsing';
|
import { parseProductName } from '../productParsing';
|
||||||
@@ -139,6 +140,8 @@ const ProductDetails = () => {
|
|||||||
const [planningSettings, setPlanningSettings] = useState<CuttingSettings>({ familyYields: {}, productOverrides: {} });
|
const [planningSettings, setPlanningSettings] = useState<CuttingSettings>({ familyYields: {}, productOverrides: {} });
|
||||||
const [isPlanningModalOpen, setIsPlanningModalOpen] = useState(false);
|
const [isPlanningModalOpen, setIsPlanningModalOpen] = useState(false);
|
||||||
const [isSavingPlanning, setIsSavingPlanning] = useState(false);
|
const [isSavingPlanning, setIsSavingPlanning] = useState(false);
|
||||||
|
const [variantCurrentPage, setVariantCurrentPage] = useState(1);
|
||||||
|
const [variantItemsPerPage, setVariantItemsPerPage] = useState(5);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let isMounted = true;
|
let isMounted = true;
|
||||||
@@ -179,6 +182,7 @@ const ProductDetails = () => {
|
|||||||
if (isMounted) {
|
if (isMounted) {
|
||||||
setDetails(productDetails);
|
setDetails(productDetails);
|
||||||
setComposition(productComposition);
|
setComposition(productComposition);
|
||||||
|
setVariantCurrentPage(1);
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
setIsCompositionLoading(false);
|
setIsCompositionLoading(false);
|
||||||
}
|
}
|
||||||
@@ -331,6 +335,10 @@ const ProductDetails = () => {
|
|||||||
: formatDateBucketLongLabel(selectedProductPoint.date, dateBucket)
|
: formatDateBucketLongLabel(selectedProductPoint.date, dateBucket)
|
||||||
: '';
|
: '';
|
||||||
const maxVariantQuantity = Math.max(...variantBreakdown.map(variant => variant.quantitySold), 0);
|
const maxVariantQuantity = Math.max(...variantBreakdown.map(variant => variant.quantitySold), 0);
|
||||||
|
const variantTotalPages = Math.ceil(variantBreakdown.length / variantItemsPerPage);
|
||||||
|
const safeVariantCurrentPage = Math.min(variantCurrentPage, variantTotalPages || 1);
|
||||||
|
const variantStartIndex = (safeVariantCurrentPage - 1) * variantItemsPerPage;
|
||||||
|
const paginatedVariantBreakdown = variantBreakdown.slice(variantStartIndex, variantStartIndex + variantItemsPerPage);
|
||||||
return (
|
return (
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
<div className="flex flex-col md:flex-row md:items-center justify-between gap-4">
|
<div className="flex flex-col md:flex-row md:items-center justify-between gap-4">
|
||||||
@@ -606,7 +614,7 @@ const ProductDetails = () => {
|
|||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
{variantBreakdown.map(variant => {
|
{paginatedVariantBreakdown.map(variant => {
|
||||||
const width = maxVariantQuantity ? Math.max(4, (variant.quantitySold / maxVariantQuantity) * 100) : 0;
|
const width = maxVariantQuantity ? Math.max(4, (variant.quantitySold / maxVariantQuantity) * 100) : 0;
|
||||||
const metadata = parseProductName(variant.name);
|
const metadata = parseProductName(variant.name);
|
||||||
|
|
||||||
@@ -614,7 +622,9 @@ const ProductDetails = () => {
|
|||||||
<div key={variant.id} className="rounded-xl border border-dark-border bg-dark-input/45 p-4">
|
<div key={variant.id} className="rounded-xl border border-dark-border bg-dark-input/45 p-4">
|
||||||
<div className="flex flex-col gap-2 md:flex-row md:items-start md:justify-between">
|
<div className="flex flex-col gap-2 md:flex-row md:items-start md:justify-between">
|
||||||
<div className="min-w-0">
|
<div className="min-w-0">
|
||||||
<div className="truncate text-sm font-bold text-dark-text">{variant.name}</div>
|
<Link to={`/products/${variant.id}`} className="block truncate text-sm font-bold text-dark-text transition-colors hover:text-brand-primary hover:underline" title={`Ver produto ${variant.name}`}>
|
||||||
|
{variant.name}
|
||||||
|
</Link>
|
||||||
<div className="mt-1 flex flex-wrap items-center gap-2 text-[11px] font-medium text-dark-muted">
|
<div className="mt-1 flex flex-wrap items-center gap-2 text-[11px] font-medium text-dark-muted">
|
||||||
<span>#{variant.id}</span>
|
<span>#{variant.id}</span>
|
||||||
{metadata.color && (
|
{metadata.color && (
|
||||||
@@ -655,6 +665,25 @@ const ProductDetails = () => {
|
|||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
{variantBreakdown.length > variantItemsPerPage && (
|
||||||
|
<PaginationControls
|
||||||
|
totalItems={variantBreakdown.length}
|
||||||
|
currentPage={safeVariantCurrentPage}
|
||||||
|
totalPages={variantTotalPages}
|
||||||
|
pageSize={variantItemsPerPage}
|
||||||
|
pageSizeOptions={[5, 10, 20]}
|
||||||
|
itemLabel="variações"
|
||||||
|
pageSizeLabel="por página"
|
||||||
|
startIndex={variantStartIndex}
|
||||||
|
endIndex={Math.min(variantStartIndex + variantItemsPerPage, variantBreakdown.length)}
|
||||||
|
onPageChange={setVariantCurrentPage}
|
||||||
|
onPageSizeChange={(pageSize) => {
|
||||||
|
setVariantItemsPerPage(pageSize);
|
||||||
|
setVariantCurrentPage(1);
|
||||||
|
}}
|
||||||
|
className="mt-5 border-t border-dark-border pt-4"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user