From 5f7f9d94d4794697d48cc9b2b6b110367b3afdf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cau=C3=AA=20Faleiros?= Date: Tue, 11 Aug 2026 10:40:41 -0300 Subject: [PATCH] Add focused cut item editor --- src/pages/Cutting.tsx | 105 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 96 insertions(+), 9 deletions(-) diff --git a/src/pages/Cutting.tsx b/src/pages/Cutting.tsx index d835a48..d9565e1 100644 --- a/src/pages/Cutting.tsx +++ b/src/pages/Cutting.tsx @@ -5,7 +5,6 @@ import DateRangePicker from '../components/DateRangePicker'; import PaginationControls from '../components/PaginationControls'; import ProductColorBadge from '../components/ProductColorBadge'; import RefreshStatus from '../components/RefreshStatus'; -import { buildCuttingSkuConfigPath } from '../catalogLinks'; import { CUT_FAMILY_RULES, buildCutPlan, buildOpenProductionByProductId, type CutFamilyKey, type CutIssue, type CutPlanSkuRow, type CutProductOverride } from '../analytics/cutting'; import { createProductionOrders, exportToCSV, fetchCuttingSettings, fetchProductAnalytics, fetchProductCompositions, fetchProductionOrders, fetchStock, saveCuttingSettings } from '../dataService'; import type { CuttingSettings, DateRange, ProductAnalyticsItem, ProductComposition, ProductionOrderItem, StockData } from '../types'; @@ -160,6 +159,9 @@ const Cutting = () => { const [itemsPerPage, setItemsPerPage] = useState(10); const [isGeneratingOrders, setIsGeneratingOrders] = useState(false); const [isOrderPreviewOpen, setIsOrderPreviewOpen] = useState(false); + const [editingCutRow, setEditingCutRow] = useState(null); + const [quickCutEdit, setQuickCutEdit] = useState({}); + const [isQuickCutEditSaving, setIsQuickCutEditSaving] = useState(false); const [activeCuttingView, setActiveCuttingView] = useState('plan'); const [generationMessage, setGenerationMessage] = useState(''); const cutConfigSection = searchParams.get('config'); @@ -410,12 +412,14 @@ const Cutting = () => { }, [correctionItemsPerPage, correctionRows, cutConfigSection, targetCorrectionSku]); useEffect(() => { - if (!isSettingsOpen && !isOrderPreviewOpen) return undefined; + if (!isSettingsOpen && !isOrderPreviewOpen && !editingCutRow) return undefined; const closeOnEscape = (event: KeyboardEvent) => { if (event.key === 'Escape') { if (isOrderPreviewOpen) { setIsOrderPreviewOpen(false); + } else if (editingCutRow) { + setEditingCutRow(null); } else { setIsSettingsOpen(false); } @@ -429,7 +433,7 @@ const Cutting = () => { document.body.style.overflow = previousOverflow; document.removeEventListener('keydown', closeOnEscape); }; - }, [isOrderPreviewOpen, isSettingsOpen]); + }, [editingCutRow, isOrderPreviewOpen, isSettingsOpen]); const updateFamilyYield = (familyKey: CutFamilyKey, value: string) => { const parsedValue = Number(value); @@ -503,6 +507,55 @@ const Cutting = () => { setIsSettingsOpen(true); }; + const openQuickCutEdit = (row: CutPlanSkuRow) => { + const override = cuttingSettings.productOverrides[row.id] || {}; + setEditingCutRow(row); + setQuickCutEdit({ + familyKey: override.familyKey || '', + color: override.color || '', + size: override.size || '' + }); + }; + + const saveQuickCutEdit = async () => { + if (!editingCutRow) return; + const normalizedOverride: CutProductOverride = { + familyKey: quickCutEdit.familyKey || '', + color: quickCutEdit.color || '', + size: quickCutEdit.size || '' + }; + const productOverrides = { ...cuttingSettings.productOverrides }; + if (!normalizedOverride.familyKey && !normalizedOverride.color && !normalizedOverride.size) { + delete productOverrides[editingCutRow.id]; + } else { + productOverrides[editingCutRow.id] = normalizedOverride; + } + const nextSettings = { ...cuttingSettings, productOverrides }; + setIsQuickCutEditSaving(true); + try { + const savedSettings = await saveCuttingSettings(nextSettings); + setCuttingSettings(savedSettings); + localStorage.setItem(SETTINGS_STORAGE_KEY, JSON.stringify(savedSettings)); + setHasUnsavedSettings(false); + setSaveStatus('saved'); + setEditingCutRow(null); + } catch (error) { + console.error('Save quick cut edit failed', error); + setSaveStatus('error'); + } finally { + setIsQuickCutEditSaving(false); + } + }; + + const openBulkCorrectionForRow = (row: CutPlanSkuRow) => { + const correctionIndex = correctionRows.findIndex(item => item.id === row.id); + setEditingCutRow(null); + setSettingsSection('corrections'); + setCorrectionIssueFilter('all'); + if (correctionIndex >= 0) setCorrectionPage(Math.floor(correctionIndex / correctionItemsPerPage) + 1); + setIsSettingsOpen(true); + }; + const exportRows = () => { exportToCSV(filteredRows.map(row => ({ 'ID Produto': row.id, @@ -813,6 +866,39 @@ const Cutting = () => { )} + {editingCutRow && ( +
!isQuickCutEditSaving && setEditingCutRow(null)}> +
event.stopPropagation()}> +
+
+

Editar dados de corte

+

{editingCutRow.name}

+

#{editingCutRow.id}

+
+ +
+
+
+ {editingCutRow.family.materialLabel} + + {editingCutRow.size || 'Sem tamanho'} +
+

Altere apenas quando a leitura automática do SKU estiver incorreta. Salvar atualiza este SKU imediatamente.

+ +
+ + +
+ +
+
+ +
+
+
+
+ )} + {isSettingsOpen && (
{ {renderCutStatus(row)}
- openQuickCutEdit(row)} + className="inline-flex h-8 w-8 items-center justify-center rounded-lg bg-dark-input text-dark-text transition-colors hover:bg-dark-border cursor-pointer" + title={`Editar dados de corte do SKU ${row.id}`} + aria-label={`Editar dados de corte do SKU ${row.id}`} > - +