From aca37c4a99b3a9ca9ed2a1af041ecaa1663546c6 Mon Sep 17 00:00:00 2001 From: Christian Vidal Wolf Date: Thu, 23 Apr 2026 12:58:51 +0200 Subject: [PATCH] Feature: Add ITEM TO LOGISTIC column to Pricing Units tab. - Integrated new column after TYPE. - Enabled inline editing with auto-save. - Added field to the full row EditPanel. - Configured dynamic column detection in types.ts. --- src/App.tsx | 3 +- src/components/EditPanel.tsx | 11 +++++++ src/components/PricingView.tsx | 55 +++++++++++++++++++++++++++++++++- src/types.ts | 6 ++-- 4 files changed, 71 insertions(+), 4 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index b28cece..9909c12 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -147,7 +147,8 @@ export default function App() { resolvedCols.VERIFIED_DIMS, resolvedCols.VALIDATED_CHECK, resolvedCols.VALIDATED_NOTE, - resolvedCols.PRODUCT_TYPE + resolvedCols.PRODUCT_TYPE, + resolvedCols.ITEM_TO_LOGISTIC ]); headers.forEach((h: any, i: number) => { diff --git a/src/components/EditPanel.tsx b/src/components/EditPanel.tsx index 0ecd21a..eb53dbb 100644 --- a/src/components/EditPanel.tsx +++ b/src/components/EditPanel.tsx @@ -143,6 +143,8 @@ export function EditPanel({ row, rowIndex, onSave, onClose, onCaptureState }: Ed outerH: row[COLUMNS.OUTER_H] !== undefined && row[COLUMNS.OUTER_H] !== null ? String(row[COLUMNS.OUTER_H]) : '', unitsOuter: row[COLUMNS.UNITS_OUTER] !== undefined && row[COLUMNS.UNITS_OUTER] !== null ? String(row[COLUMNS.UNITS_OUTER]) : '', moq: row[COLUMNS.MOQ] !== undefined && row[COLUMNS.MOQ] !== null ? String(row[COLUMNS.MOQ]) : '', + productType: row[COLUMNS.PRODUCT_TYPE] !== undefined && row[COLUMNS.PRODUCT_TYPE] !== null ? String(row[COLUMNS.PRODUCT_TYPE]) : '', + itemToLogistic: row[COLUMNS.ITEM_TO_LOGISTIC] !== undefined && row[COLUMNS.ITEM_TO_LOGISTIC] !== null ? String(row[COLUMNS.ITEM_TO_LOGISTIC]) : '', }); const [loadingField, setLoadingField] = useState(null); @@ -178,6 +180,8 @@ export function EditPanel({ row, rowIndex, onSave, onClose, onCaptureState }: Ed moq: COLUMNS.MOQ, detailsDe: COLUMNS.DETAILS_DE, detailsEn: COLUMNS.DETAILS_EN, + productType: COLUMNS.PRODUCT_TYPE, + itemToLogistic: COLUMNS.ITEM_TO_LOGISTIC, }; const colIndex = (colMap as Record)[field as string]; if (colIndex === undefined) return false; @@ -307,6 +311,8 @@ export function EditPanel({ row, rowIndex, onSave, onClose, onCaptureState }: Ed newRow[COLUMNS.MOQ] = formData.moq; newRow[COLUMNS.DETAILS_DE] = formData.detailsDe; newRow[COLUMNS.DETAILS_EN] = formData.detailsEn; + newRow[COLUMNS.PRODUCT_TYPE] = formData.productType; + newRow[COLUMNS.ITEM_TO_LOGISTIC] = formData.itemToLogistic; onSave(rowIndex, newRow); }; @@ -393,6 +399,11 @@ export function EditPanel({ row, rowIndex, onSave, onClose, onCaptureState }: Ed setFormData(p => ({...p, unitsOuter: val}))} /> setFormData(p => ({...p, moq: val}))} /> + +
+ setFormData(p => ({...p, productType: val}))} /> + setFormData(p => ({...p, itemToLogistic: val}))} /> +
>({}); const [weightIssueFilter, setWeightIssueFilter] = useState<'all' | 'with' | 'without'>('all'); const [editingType, setEditingType] = useState<{ rowIndex: number; value: string } | null>(null); + const [editingLogistic, setEditingLogistic] = useState<{ rowIndex: number; value: string } | null>(null); const [typeSuggestions, setTypeSuggestions] = useState([]); const typeInputRef = useRef(null); + const logisticInputRef = useRef(null); const [sortConfig, setSortConfig] = useState<{ key: string | number; direction: 'asc' | 'desc' | null }>({ key: null, direction: null }); const [isSearchOpen, setIsSearchOpen] = useState(false); @@ -487,6 +490,20 @@ export function PricingView({ data, headers, onSaveRow, onCaptureState, onEdit, ); }; + const startEditLogistic = (rowIndex: number, currentValue: string) => { + setEditingLogistic({ rowIndex, value: currentValue }); + setTimeout(() => logisticInputRef.current?.focus(), 0); + }; + + const commitLogisticEdit = useCallback(async (rowIndex: number, value: string) => { + setEditingLogistic(null); + const original = data[rowIndex]; + const newRow = [...original]; + newRow[COLUMNS.ITEM_TO_LOGISTIC] = value; + onCaptureState(`Updated logistic info for ${original[COLUMNS.ARTICLE_NO]}`); + await onSaveRow(rowIndex, newRow); + }, [data, onSaveRow, onCaptureState, COLUMNS]); + // ── Column helpers ──────────────────────────────────────────────────────── const pricingEditableCols: DetectedCol[] = [ ...(uvpIdx >= 0 ? [{ index: uvpIdx, name: headers[uvpIdx] || 'UVP' }] : []), @@ -885,6 +902,11 @@ export function PricingView({ data, headers, onSaveRow, onCaptureState, onEdit, { e.stopPropagation(); handleResizeStart(e, 'productType', columnWidths.productType); }} /> + handleSort('itemToLogistic')}> + Item to Logistic + { e.stopPropagation(); handleResizeStart(e, 'itemToLogistic', columnWidths.itemToLogistic); }} /> + + {pricingEditableCols.map(col => { const colKey = `prc_${col.index}`; const width = columnWidths[colKey] ?? 100; @@ -1071,7 +1093,7 @@ export function PricingView({ data, headers, onSaveRow, onCaptureState, onEdit,
- Issues + Weight Issues + )} + + {/* Pricing editable cells */} {pricingEditableCols.map(col => { const isEditing = editingCell?.rowIndex === dataIndex && editingCell?.colIndex === col.index; diff --git a/src/types.ts b/src/types.ts index fdfe2ee..8e0aabd 100644 --- a/src/types.ts +++ b/src/types.ts @@ -40,7 +40,8 @@ export const COLUMNS = { VERIFIED_DIMS: 100, VALIDATED_CHECK: 101, VALIDATED_NOTE: 102, - PRODUCT_TYPE: 103 + PRODUCT_TYPE: 103, + ITEM_TO_LOGISTIC: 104 }; // Search patterns for dynamic detection @@ -75,7 +76,8 @@ export const COLUMN_PATTERNS: Record = { VERIFIED_DIMS: ['verified'], VALIDATED_CHECK: ['validated'], VALIDATED_NOTE: ['note'], - PRODUCT_TYPE: ['product', 'type'] + PRODUCT_TYPE: ['product', 'type'], + ITEM_TO_LOGISTIC: ['item', 'to', 'logistic'] }; export function resolveColumnIndices(headers: string[]): typeof COLUMNS {