Paginate production plan confirmation
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 37s

This commit is contained in:
Cauê Faleiros
2026-08-27 20:12:11 -03:00
parent 7ae230ed2e
commit acf542f2d5

View File

@@ -168,6 +168,8 @@ const Cutting = () => {
const [previewStep, setPreviewStep] = useState<PreviewStep>('selection'); const [previewStep, setPreviewStep] = useState<PreviewStep>('selection');
const [previewPage, setPreviewPage] = useState(1); const [previewPage, setPreviewPage] = useState(1);
const [previewItemsPerPage, setPreviewItemsPerPage] = useState(10); const [previewItemsPerPage, setPreviewItemsPerPage] = useState(10);
const [confirmationPage, setConfirmationPage] = useState(1);
const [confirmationItemsPerPage, setConfirmationItemsPerPage] = useState(10);
const [previewReviewFilter, setPreviewReviewFilter] = useState<PreviewReviewFilter>('all'); const [previewReviewFilter, setPreviewReviewFilter] = useState<PreviewReviewFilter>('all');
const [selectedPreviewRowIds, setSelectedPreviewRowIds] = useState<string[]>([]); const [selectedPreviewRowIds, setSelectedPreviewRowIds] = useState<string[]>([]);
const [previewQuantityOverrides, setPreviewQuantityOverrides] = useState<Record<string, string>>({}); const [previewQuantityOverrides, setPreviewQuantityOverrides] = useState<Record<string, string>>({});
@@ -403,6 +405,10 @@ const Cutting = () => {
const selectedIds = new Set(selectedPreviewRowIds); const selectedIds = new Set(selectedPreviewRowIds);
return rowsAvailableForOrder.filter(row => selectedIds.has(row.id)); return rowsAvailableForOrder.filter(row => selectedIds.has(row.id));
}, [rowsAvailableForOrder, selectedPreviewRowIds]); }, [rowsAvailableForOrder, selectedPreviewRowIds]);
const confirmationTotalPages = Math.ceil(selectedPreviewRows.length / confirmationItemsPerPage);
const safeConfirmationPage = Math.min(confirmationPage, confirmationTotalPages || 1);
const confirmationStartIndex = (safeConfirmationPage - 1) * confirmationItemsPerPage;
const paginatedConfirmationRows = selectedPreviewRows.slice(confirmationStartIndex, confirmationStartIndex + confirmationItemsPerPage);
const orderPreviewTotalUnits = useMemo(() => ( const orderPreviewTotalUnits = useMemo(() => (
selectedPreviewRows.reduce((total, row) => total + getPreviewQuantity(row), 0) selectedPreviewRows.reduce((total, row) => total + getPreviewQuantity(row), 0)
), [getPreviewQuantity, selectedPreviewRows]); ), [getPreviewQuantity, selectedPreviewRows]);
@@ -686,6 +692,7 @@ const Cutting = () => {
setGenerationMessage(''); setGenerationMessage('');
setPreviewPage(1); setPreviewPage(1);
setConfirmationPage(1);
setPreviewReviewFilter('all'); setPreviewReviewFilter('all');
setSelectedPreviewRowIds(rowsAvailableForOrder.map(row => row.id)); setSelectedPreviewRowIds(rowsAvailableForOrder.map(row => row.id));
setPreviewQuantityOverrides({}); setPreviewQuantityOverrides({});
@@ -997,7 +1004,7 @@ const Cutting = () => {
{previewRowsWithIssues > 0 && <span className="text-xs font-bold text-amber-300">{formatNumber(previewRowsWithIssues)} para revisar</span>} {previewRowsWithIssues > 0 && <span className="text-xs font-bold text-amber-300">{formatNumber(previewRowsWithIssues)} para revisar</span>}
</div> </div>
<div className="mt-3 divide-y divide-dark-border overflow-hidden rounded-lg border border-dark-border bg-dark-card"> <div className="mt-3 divide-y divide-dark-border overflow-hidden rounded-lg border border-dark-border bg-dark-card">
{selectedPreviewRows.map(row => ( {paginatedConfirmationRows.map(row => (
<div key={row.id} className="grid gap-3 px-3 py-3 lg:grid-cols-[minmax(0,1fr)_100px] lg:items-center"> <div key={row.id} className="grid gap-3 px-3 py-3 lg:grid-cols-[minmax(0,1fr)_100px] lg:items-center">
<div className="min-w-0"> <div className="min-w-0">
<p className="truncate text-sm font-bold text-dark-text" title={row.name}>{row.name}</p> <p className="truncate text-sm font-bold text-dark-text" title={row.name}>{row.name}</p>
@@ -1014,6 +1021,20 @@ const Cutting = () => {
</div> </div>
))} ))}
</div> </div>
<PaginationControls
totalItems={selectedPreviewRows.length}
currentPage={safeConfirmationPage}
totalPages={confirmationTotalPages}
pageSize={confirmationItemsPerPage}
pageSizeOptions={[10, 20, 50]}
itemLabel="OPs"
pageSizeLabel="por página"
startIndex={confirmationStartIndex}
endIndex={Math.min(confirmationStartIndex + confirmationItemsPerPage, selectedPreviewRows.length)}
onPageChange={setConfirmationPage}
onPageSizeChange={(pageSize) => { setConfirmationItemsPerPage(pageSize); setConfirmationPage(1); }}
className="mt-3 border-t border-dark-border pt-3"
/>
<p className="mt-3 text-xs font-semibold text-dark-muted">A quantidade sugerida vem da cobertura. Ajustes manuais ficam marcados na OP, e o resultado real é confirmado durante a execução.</p> <p className="mt-3 text-xs font-semibold text-dark-muted">A quantidade sugerida vem da cobertura. Ajustes manuais ficam marcados na OP, e o resultado real é confirmado durante a execução.</p>
</div> </div>
</div>} </div>}
@@ -1079,7 +1100,7 @@ const Cutting = () => {
<td className="px-4 py-3 font-bold whitespace-nowrap text-dark-text">{formatNumber(row.projectedDemand, 1)} un.</td> <td className="px-4 py-3 font-bold whitespace-nowrap text-dark-text">{formatNumber(row.projectedDemand, 1)} un.</td>
<td className="px-4 py-3 whitespace-nowrap"><div className="font-bold text-dark-text">{formatNumber(row.availableQuantity)} un.</div>{row.openProductionQuantity ? <div className="mt-1 text-[10px] font-semibold text-dark-muted">{formatNumber(row.openProductionQuantity)} em OP</div> : null}</td> <td className="px-4 py-3 whitespace-nowrap"><div className="font-bold text-dark-text">{formatNumber(row.availableQuantity)} un.</div>{row.openProductionQuantity ? <div className="mt-1 text-[10px] font-semibold text-dark-muted">{formatNumber(row.openProductionQuantity)} em OP</div> : null}</td>
<td className="px-4 py-3"> <td className="px-4 py-3">
<div className="flex items-center gap-2"> <div className="flex items-center gap-3">
{renderIssueBadge(row)} {renderIssueBadge(row)}
<button <button
type="button" type="button"
@@ -1141,7 +1162,7 @@ const Cutting = () => {
</button> </button>
<button <button
type="button" type="button"
onClick={() => previewStep === 'selection' ? setPreviewStep('confirmation') : void generateProductionOrders()} onClick={() => previewStep === 'selection' ? (setConfirmationPage(1), setPreviewStep('confirmation')) : void generateProductionOrders()}
disabled={isGeneratingOrders || !selectedPreviewRows.length} disabled={isGeneratingOrders || !selectedPreviewRows.length}
className="inline-flex items-center justify-center gap-2 rounded-xl border border-brand-primary/30 bg-brand-primary/15 px-4 py-2 text-sm font-bold text-brand-primary transition-colors hover:border-brand-primary disabled:cursor-not-allowed disabled:opacity-50 cursor-pointer" className="inline-flex items-center justify-center gap-2 rounded-xl border border-brand-primary/30 bg-brand-primary/15 px-4 py-2 text-sm font-bold text-brand-primary transition-colors hover:border-brand-primary disabled:cursor-not-allowed disabled:opacity-50 cursor-pointer"
> >