From 5c9d1013494fcbe4148a8dc0bfd7fc4c7226ce23 Mon Sep 17 00:00:00 2001 From: Christian Vidal Wolf Date: Sun, 29 Mar 2026 17:43:57 +0200 Subject: [PATCH] Implement granular synchronization for Outer Box, Units, and MOQ separately --- src/components/DimensionsView.tsx | 106 +++++++++++++++++++++++------- 1 file changed, 83 insertions(+), 23 deletions(-) diff --git a/src/components/DimensionsView.tsx b/src/components/DimensionsView.tsx index 29d806d..eaa7657 100644 --- a/src/components/DimensionsView.tsx +++ b/src/components/DimensionsView.tsx @@ -1,6 +1,6 @@ import React, { useState, useMemo } from 'react'; import { ExcelRow, COLUMNS } from '../types'; -import { AlertTriangle, CheckCircle2, ChevronDown, ChevronRight, Edit2, Package, Boxes, Scale, Loader2, RefreshCw } from 'lucide-react'; +import { AlertTriangle, CheckCircle2, ChevronDown, ChevronRight, Edit2, Package, Boxes, Scale, Loader2, RefreshCw, Layers } from 'lucide-react'; import { cn } from '../lib/utils'; interface DimensionsViewProps { @@ -26,7 +26,7 @@ interface DimensionGroup { export function DimensionsView({ data, headers, onEdit, onSaveRow, onCaptureState }: DimensionsViewProps) { const [expandedGroups, setExpandedGroups] = useState>(new Set()); const [showOnlyInconsistent, setShowOnlyInconsistent] = useState(true); - const [syncing, setSyncing] = useState(null); + const [syncing, setSyncing] = useState<{ key: string, field: string } | null>(null); const groups = useMemo(() => { const groupMap = new Map(); @@ -45,7 +45,8 @@ export function DimensionsView({ data, headers, onEdit, onSaveRow, onCaptureStat const result: DimensionGroup[] = []; groupMap.forEach((rows, key) => { - if (key === '0x0x0' || key === 'xx' || key === '0x0x0') return; // Skip empty/placeholder groups + // Skip empty/placeholder groups (0x0x0 or empty fields) + if (key === '0x0x0' || key === 'xx' || key === 'x x') return; const first = rows[0].row; const firstOuter = `${first[COLUMNS.OUTER_L]}x${first[COLUMNS.OUTER_W]}x${first[COLUMNS.OUTER_H]}`; @@ -96,13 +97,15 @@ export function DimensionsView({ data, headers, onEdit, onSaveRow, onCaptureStat setExpandedGroups(next); }; - const handleSyncFromRow = async (group: DimensionGroup, sourceRow: ExcelRow) => { - if (!window.confirm(`Apply measures of product ${sourceRow[COLUMNS.ARTICLE_NO]} to all ${group.rows.length} products in this group?`)) { + const handleSyncField = async (group: DimensionGroup, sourceRow: ExcelRow, fieldType: 'outer' | 'units' | 'moq') => { + const fieldLabel = fieldType === 'outer' ? 'Outer Box Dimensions' : fieldType === 'units' ? 'Units per Outer' : 'MOQ'; + if (!window.confirm(`Sync ALL products in this group to match "${fieldLabel}" from product ${sourceRow[COLUMNS.ARTICLE_NO]}?`)) { return; } - onCaptureState(`Synced ${group.rows.length} products to match ${sourceRow[COLUMNS.ARTICLE_NO]}`); - setSyncing(group.key); + onCaptureState(`Bulk synced ${fieldLabel} in group ${group.innerDims}`); + setSyncing({ key: group.key, field: fieldType }); + try { const outerL = sourceRow[COLUMNS.OUTER_L]; const outerW = sourceRow[COLUMNS.OUTER_W]; @@ -111,16 +114,49 @@ export function DimensionsView({ data, headers, onEdit, onSaveRow, onCaptureStat const moq = sourceRow[COLUMNS.MOQ]; for (const { row, index } of group.rows) { - // Skip updating the source row itself (though it doesn't hurt) if (row === sourceRow) continue; + const updatedRow = [...row]; + + if (fieldType === 'outer') { + updatedRow[COLUMNS.OUTER_L] = outerL; + updatedRow[COLUMNS.OUTER_W] = outerW; + updatedRow[COLUMNS.OUTER_H] = outerH; + } else if (fieldType === 'units') { + updatedRow[COLUMNS.UNITS_OUTER] = unitsOuter; + } else if (fieldType === 'moq') { + updatedRow[COLUMNS.MOQ] = moq; + } + + await onSaveRow(index, updatedRow); + } + } finally { + setSyncing(null); + } + }; + const handleFullSync = async (group: DimensionGroup, sourceRow: ExcelRow) => { + if (!window.confirm(`Sync ALL Packaging & MOQ data in this group to match product ${sourceRow[COLUMNS.ARTICLE_NO]}?`)) { + return; + } + + onCaptureState(`Full sync of packaging data in group ${group.innerDims}`); + setSyncing({ key: group.key, field: 'all' }); + + try { + const outerL = sourceRow[COLUMNS.OUTER_L]; + const outerW = sourceRow[COLUMNS.OUTER_W]; + const outerH = sourceRow[COLUMNS.OUTER_H]; + const unitsOuter = sourceRow[COLUMNS.UNITS_OUTER]; + const moq = sourceRow[COLUMNS.MOQ]; + + for (const { row, index } of group.rows) { + if (row === sourceRow) continue; const updatedRow = [...row]; updatedRow[COLUMNS.OUTER_L] = outerL; updatedRow[COLUMNS.OUTER_W] = outerW; updatedRow[COLUMNS.OUTER_H] = outerH; updatedRow[COLUMNS.UNITS_OUTER] = unitsOuter; updatedRow[COLUMNS.MOQ] = moq; - await onSaveRow(index, updatedRow); } } finally { @@ -212,7 +248,7 @@ export function DimensionsView({ data, headers, onEdit, onSaveRow, onCaptureStat {group.isInconsistent && !expandedGroups.has(group.key) && (
- OPEN TO SYNC + OPEN TO SYNC FIELDS
)} @@ -239,40 +275,64 @@ export function DimensionsView({ data, headers, onEdit, onSaveRow, onCaptureStat
{row[COLUMNS.ARTICLE_NAME]}
- {row[COLUMNS.INNER_L]} × {row[COLUMNS.INNER_W]} × {row[COLUMNS.INNER_H]} + {row[COLUMNS.INNER_L] || '-'} × {row[COLUMNS.INNER_W] || '-'} × {row[COLUMNS.INNER_H] || '-'} - {row[COLUMNS.OUTER_L]} × {row[COLUMNS.OUTER_W]} × {row[COLUMNS.OUTER_H]} + {row[COLUMNS.OUTER_L] || '-'} × {row[COLUMNS.OUTER_W] || '-'} × {row[COLUMNS.OUTER_H] || '-'} + - {row[COLUMNS.UNITS_OUTER]} + {row[COLUMNS.UNITS_OUTER] || '-'} + - {row[COLUMNS.MOQ]} + {row[COLUMNS.MOQ] || '-'} +