diff --git a/src/pages/Cutting.tsx b/src/pages/Cutting.tsx index 3763cf7..91b87a7 100644 --- a/src/pages/Cutting.tsx +++ b/src/pages/Cutting.tsx @@ -1,6 +1,6 @@ import { useEffect, useMemo, useState } from 'react'; import { Link, useOutletContext, useSearchParams } from 'react-router-dom'; -import { AlertTriangle, ArrowLeft, ClipboardList, Download, Eye, Layers3, Pencil, RotateCcw, Ruler, Save as SaveIcon, Scissors, Search, Settings2, X } from 'lucide-react'; +import { AlertTriangle, ArrowLeft, ArrowRight, ClipboardList, Download, Eye, Layers3, Pencil, RotateCcw, Ruler, Save as SaveIcon, Scissors, Search, Settings2, X } from 'lucide-react'; import DateRangePicker from '../components/DateRangePicker'; import PaginationControls from '../components/PaginationControls'; import ProductColorBadge from '../components/ProductColorBadge'; @@ -18,6 +18,7 @@ type CutProductIssue = Exclude; type CorrectionIssueFilter = CutProductIssue | 'all'; type SettingsSection = 'rules' | 'corrections'; type CuttingView = 'plan' | 'families' | 'issues'; +type PreviewStep = 'selection' | 'confirmation'; type MaterialReadiness = { status: 'ready' | 'material_ready' | 'blocked' | 'missing'; blockers: string[] }; type CutMaterialRequirement = { key: string; label: string; unit: string; quantity: number }; @@ -163,6 +164,7 @@ const Cutting = () => { const [itemsPerPage, setItemsPerPage] = useState(10); const [isGeneratingOrders, setIsGeneratingOrders] = useState(false); const [isOrderPreviewOpen, setIsOrderPreviewOpen] = useState(false); + const [previewStep, setPreviewStep] = useState('selection'); const [previewPage, setPreviewPage] = useState(1); const [previewItemsPerPage, setPreviewItemsPerPage] = useState(10); const [selectedPreviewRowIds, setSelectedPreviewRowIds] = useState([]); @@ -670,6 +672,7 @@ const Cutting = () => { setLotSelections({}); setProductionPlanForm({ name: cutPlanReference, contractor: '', expectedDate: '', notes: '' }); setIsPlanDetailsOpen(false); + setPreviewStep('selection'); setIsOrderPreviewOpen(true); }; @@ -885,9 +888,11 @@ const Cutting = () => { >
-

Prévia das OPs

+

{previewStep === 'selection' ? 'Selecionar OPs' : 'Confirmar plano'}

- Escolha os SKUs para criar ordens locais das necessidades do filtro atual. + {previewStep === 'selection' + ? 'Escolha os SKUs que entrarão neste plano de produção.' + : 'Revise o plano e as reservas antes de criar as ordens locais.'}

-
+
+ + 1 + Selecionar OPs + + + + 2 + Confirmar plano + +
+ + {previewStep === 'selection' &&
{formatNumber(selectedPreviewRows.length)} selecionada{selectedPreviewRows.length === 1 ? '' : 's'} · @@ -910,9 +927,9 @@ const Cutting = () => { {previewRowsWithIssues > 0 && <>·{formatNumber(previewRowsWithIssues)} para revisar}
Cobertura de {formatNumber(targetCoverageDays)} dias -
+
} -
+ {previewStep === 'confirmation' &&
} -
+
} + {previewStep === 'confirmation' &&
+
+
+
+

OPs incluídas

+

{formatNumber(selectedPreviewRows.length)} SKU{selectedPreviewRows.length === 1 ? '' : 's'} · {formatNumber(orderPreviewTotalUnits)} un. para cortar

+
+ {previewRowsWithIssues > 0 && {formatNumber(previewRowsWithIssues)} para revisar} +
+
+ {selectedPreviewRows.map(row => ( +
+
+

{row.name}

+
+ #{row.id} + {row.family.materialLabel} + + {row.size || 'Sem tamanho'} +
+
+ {formatNumber(row.suggestedCutQuantity)} un. +
+ ))} +
+
+
} + + {previewStep === 'selection' && <>

Todos os SKUs abaixo estão aptos para gerar OP. A seleção permanece ao trocar de página.

-
@@ -982,8 +1027,9 @@ const Cutting = () => { + } - {selectedMaterialRequirements.length > 0 &&
+ {previewStep === 'confirmation' && selectedMaterialRequirements.length > 0 &&

Reservar lotes para este corte

@@ -994,7 +1040,7 @@ const Cutting = () => { {selectedMaterialRequirements.length ?
{selectedMaterialRequirements.map(requirement => { const selection = lotSelections[requirement.key] || { lotId: '', quantity: '' }; const lots = supplyLots.filter(lot => { const lotKey = normalizeMaterialKey(lot.product); const materialMatch = lotKey === requirement.key || lotKey === normalizeMaterialKey(requirement.label); return lot.availableQuantity > 0 && materialMatch && lot.unit.toLowerCase() === requirement.unit.toLowerCase(); }); return ; })}
Material necessárioNecessárioLote reservadoQuantidade reservada

{requirement.label}

{requirement.key}

{formatNumber(requirement.quantity, 4)} {requirement.unit} setLotSelections(current => ({ ...current, [requirement.key]: { lotId: current[requirement.key]?.lotId || '', quantity: event.target.value } }))} disabled={!selection.lotId} className="h-9 w-32 rounded-lg border border-dark-border bg-dark-input px-2 text-right text-xs font-semibold text-dark-text outline-none placeholder:text-dark-muted focus:border-brand-primary disabled:cursor-not-allowed disabled:opacity-50" placeholder={formatNumber(requirement.quantity, 4)} />
:

Os SKUs selecionados não possuem componentes de material sincronizados. Eles podem seguir para OP, mas não geram reserva.

}
} - { onPageChange={setPreviewPage} onPageSizeChange={(pageSize) => { setPreviewItemsPerPage(pageSize); setPreviewPage(1); }} className="border-t border-dark-border px-4 py-3" - /> + />}
-

- OPs abertas já existentes para o mesmo plano e SKU serão ignoradas. +

{previewStep === 'selection' + ? 'Você poderá revisar o plano e reservar lotes na próxima etapa.' + : 'OPs abertas já existentes para o mesmo plano e SKU serão ignoradas.'}