diff --git a/src/App.tsx b/src/App.tsx index 8b30adb..991c4f7 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -122,7 +122,9 @@ export default function App() { COLUMNS.INNER_L, COLUMNS.INNER_W, COLUMNS.INNER_H, COLUMNS.OUTER_L, COLUMNS.OUTER_W, COLUMNS.OUTER_H, COLUMNS.UNITS_OUTER, COLUMNS.MOQ, - COLUMNS.VERIFIED_DIMS + COLUMNS.VERIFIED_DIMS, + COLUMNS.VALIDATED_CHECK, + COLUMNS.VALIDATED_NOTE ]); headers.forEach((h: any, i: number) => { diff --git a/src/components/MissingDataView.tsx b/src/components/MissingDataView.tsx index 69e5b7c..2ca8e32 100644 --- a/src/components/MissingDataView.tsx +++ b/src/components/MissingDataView.tsx @@ -55,7 +55,7 @@ function isEmptyOrEpoch(val: any): boolean { return false; } -type TabType = 'missingLaunch'; +type TabType = 'missingLaunch' | 'launchInconsistent' | 'upcomingLaunch'; interface EditingState { rowIndex: number; diff --git a/src/components/PricingView.tsx b/src/components/PricingView.tsx index 8fdb247..3473037 100644 --- a/src/components/PricingView.tsx +++ b/src/components/PricingView.tsx @@ -13,6 +13,7 @@ import { Filter, Check, Search, + MessageSquare, } from 'lucide-react'; import { cn } from '../lib/utils'; import { ColumnFilterPopover } from './ColumnFilterPopover'; @@ -311,6 +312,52 @@ export function PricingView({ data, headers, onSaveRow, onCaptureState, onEdit, ); }; + // ── Matrix columns (the rest) ───────────────────────────────────────────── + const displayedIndices = useMemo(() => { + const set = new Set([ + COLUMNS.ARTICLE_NO, + COLUMNS.ARTICLE_NAME, + COLUMNS.LINE, + COLUMNS.CLASSIFICATION, + COLUMNS.UNITS_OUTER, + COLUMNS.OUTER_W, + COLUMNS.OUTER_L, + COLUMNS.OUTER_H, + ]); + if (uvpIdx >= 0) set.add(uvpIdx); + srpCols.forEach(c => set.add(c.index)); + containerCols.forEach(c => set.add(c.index)); + return set; + }, [uvpIdx, srpCols, containerCols]); + + const matrixCols = useMemo(() => { + return headers + .map((h, i) => ({ index: i, name: h || '' })) + .filter(({ index }) => !displayedIndices.has(index)) + .filter(({ name }) => name.trim() !== ''); // Skip empty headers + }, [headers, displayedIndices]); + + const [noteEditor, setNoteEditor] = useState<{ rowIndex: number; text: string } | null>(null); + + const handleToggleCheck = async (rowIndex: number, checked: boolean) => { + const original = data[rowIndex]; + const newRow = [...original]; + newRow[COLUMNS.VALIDATED_CHECK] = checked; + onCaptureState(`${checked ? 'Checked' : 'Unchecked'} ${original[COLUMNS.ARTICLE_NO]}`); + await onSaveRow(rowIndex, newRow); + }; + + const saveNote = async () => { + if (!noteEditor) return; + const { rowIndex, text } = noteEditor; + const original = data[rowIndex]; + const newRow = [...original]; + newRow[COLUMNS.VALIDATED_NOTE] = text; + setNoteEditor(null); + onCaptureState(`Updated note for ${original[COLUMNS.ARTICLE_NO]}`); + await onSaveRow(rowIndex, newRow); + }; + // ── Column detection notice ─────────────────────────────────────────────── const missingCols: string[] = []; if (uvpIdx < 0) missingCols.push('UVP'); @@ -325,7 +372,40 @@ export function PricingView({ data, headers, onSaveRow, onCaptureState, onEdit, ]; return ( -
+
+ {/* ── Note Editor Modal ── */} + {noteEditor && ( +
+
+
+

+ + Validation Note +

+

{data[noteEditor.rowIndex][COLUMNS.ARTICLE_NO]}

+
+
+