From 5112a27cda3de7cecae841de73b98f64b98629f9 Mon Sep 17 00:00:00 2001 From: Christian Vidal Wolf Date: Thu, 23 Apr 2026 18:27:40 +0200 Subject: [PATCH] Feat: Implement dynamic internal column protection and Fullscreen mode. - Internal control columns (Type, Checking, etc.) now persist across Excel shifts. - Master data columns now prioritize Dropbox source of truth. - Added Fullscreen mode to all main tabs (Pricing, Descriptions, Matrix). - Improved Supabase data loading with pagination. --- src/App.tsx | 33 +++++++++++++++++++-------------- src/components/PricingView.tsx | 5 ++--- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 22d0b57..d917598 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -190,22 +190,27 @@ const articleNoIdx = resolvedCols.ARTICLE_NO; // Start with fresh Dropbox values (prices from Excel) let finalRow = [...row]; - // Load manual edits: status 'edited' = saved edits, 'pending' = unsaved edits - if (synced && (synced.status === 'edited' || synced.status === 'pending')) { - // Compare saved row vs fresh Excel row: wherever Supabase differs from Excel, - // that means the user edited that column — apply it regardless of editableColumns - // index resolution, which can vary across sessions. - const savedLen = Array.isArray(synced.data) ? synced.data.length : 0; - for (let idx = 0; idx < savedLen; idx++) { - const savedVal = synced.data[idx]; - const excelVal = row[idx]; - const savedStr = savedVal == null ? '' : String(savedVal); - const excelStr = excelVal == null ? '' : String(excelVal); - if (savedStr !== excelStr) { - // Value differs from Excel → user edited it, apply the saved value - finalRow[idx] = savedVal; + // Merge logic: Prioritize internal control columns and active session edits + if (synced && (synced.status === 'edited' || synced.status === 'pending' || synced.status === 'synced')) { + // 1. ALWAYS restore Internal Control Columns (indices >= 100) + // These are the "TYPE", "Item to Logistic", "Checking", etc. + Object.values(COLUMNS).forEach(idx => { + if (idx >= 100 && synced.data[idx] !== undefined && synced.data[idx] !== null) { + finalRow[idx] = synced.data[idx]; } + }); + + // 2. For Master Data (indices < 100, like UVP/SRP), only restore if it's an active edit (pending) + // This protects against the "Column Shift" bug where old saved indices might be wrong. + if (synced.status === 'pending') { + editableColumns.forEach(idx => { + if (idx < 100 && synced.data[idx] !== undefined && synced.data[idx] !== null) { + finalRow[idx] = synced.data[idx]; + } + }); } + + // Update row status in UI setRowStatuses(prev => ({ ...prev, [articleNo]: synced.status })); } diff --git a/src/components/PricingView.tsx b/src/components/PricingView.tsx index dba301d..426dc41 100644 --- a/src/components/PricingView.tsx +++ b/src/components/PricingView.tsx @@ -656,12 +656,11 @@ export function PricingView({ data, headers, onSaveRow, onCaptureState, onEdit, ]; return ( -
+
{isFullscreen && (