Fix applying templates to or discarding multiple rows

This commit is contained in:
2025-03-07 16:16:57 -05:00
parent b15387041b
commit 875d0b8f55
4 changed files with 138 additions and 64 deletions

View File

@@ -52,17 +52,6 @@ const SearchableTemplateSelect: React.FC<SearchableTemplateSelectProps> = ({
const [open, setOpen] = useState(false);
const [] = useState<string | null>(null);
// Debug logging
useEffect(() => {
// Only log when selectedBrand changes or on mount
console.debug('SearchableTemplateSelect brand update:', {
selectedBrand,
defaultBrand,
templatesCount: templates?.length || 0,
templatesForBrand: templates?.filter(t => t.company === selectedBrand)?.length || 0
});
}, [selectedBrand, defaultBrand, templates]);
// Set default brand when component mounts or defaultBrand changes
useEffect(() => {
if (defaultBrand) {

View File

@@ -54,7 +54,8 @@ const ValidationContainer = <T extends string>({
loadTemplates,
setData,
fields,
isLoadingTemplates
isLoadingTemplates,
rowValidationStatus
} = validationState
// Add state for tracking product lines and sublines per row
@@ -563,16 +564,37 @@ const ValidationContainer = <T extends string>({
}, [onNext, data, applyItemNumbersToData]);
const deleteSelectedRows = useCallback(() => {
// Get selected row indices
const selectedRowIndexes = Object.keys(rowSelection).map(Number);
// Get selected row keys (which may be UUIDs)
const selectedKeys = Object.entries(rowSelection)
.filter(([_, selected]) => selected === true)
.map(([key, _]) => key);
if (selectedRowIndexes.length === 0) {
console.log('Selected row keys for deletion:', selectedKeys);
if (selectedKeys.length === 0) {
toast.error("No rows selected");
return;
}
// Map UUID keys to array indices
const selectedIndices = selectedKeys.map(key => {
// Find the matching row index in the data array
const index = data.findIndex(row =>
(row.__index && row.__index === key) || // Match by __index
(String(data.indexOf(row)) === key) // Or by numeric index
);
return index;
}).filter(index => index !== -1); // Filter out any not found
console.log('Mapped row indices for deletion:', selectedIndices);
if (selectedIndices.length === 0) {
toast.error('Could not find selected rows');
return;
}
// Sort indices in descending order to avoid index shifting during removal
const sortedIndices = [...selectedRowIndexes].sort((a, b) => b - a);
const sortedIndices = [...selectedIndices].sort((a, b) => b - a);
// Create a new array without the selected rows
const newData = [...data];
@@ -592,9 +614,9 @@ const ValidationContainer = <T extends string>({
// Show success message
toast.success(
selectedRowIndexes.length === 1
selectedIndices.length === 1
? "Row deleted"
: `${selectedRowIndexes.length} rows deleted`
: `${selectedIndices.length} rows deleted`
);
// Reindex the data in the next render cycle
@@ -829,7 +851,11 @@ const ValidationContainer = <T extends string>({
<Button
variant={isFromScratch ? "destructive" : "outline"}
size="sm"
onClick={deleteSelectedRows}
onClick={() => {
console.log('Delete/Discard button clicked');
console.log('Row selection state:', rowSelection);
deleteSelectedRows();
}}
>
{isFromScratch ? "Delete Row" : translations.validationStep.discardButtonTitle || "Discard Row"}
</Button>

View File

@@ -350,6 +350,10 @@ const ValidationTable = <T extends string>({
cell: ({ row }) => {
const templateValue = row.original.__template || null;
const defaultBrand = row.original.company || undefined;
const rowIndex = data.findIndex(r => r === row.original);
console.log(`Template cell for row ${row.id}, index ${rowIndex}`);
return (
<TableCell className="p-1" style={{ width: '200px', minWidth: '200px' }}>
{isLoadingTemplates ? (
@@ -362,7 +366,7 @@ const ValidationTable = <T extends string>({
templates={templates}
value={templateValue || ''}
onValueChange={(value) => {
applyTemplate(value, [row.index]);
applyTemplate(value, [rowIndex]);
}}
getTemplateDisplayText={getTemplateDisplayText}
defaultBrand={defaultBrand}
@@ -371,7 +375,7 @@ const ValidationTable = <T extends string>({
</TableCell>
);
}
}), [templates, applyTemplate, getTemplateDisplayText, isLoadingTemplates]);
}), [templates, applyTemplate, getTemplateDisplayText, isLoadingTemplates, data]);
// Memoize field columns
const fieldColumns = useMemo(() => fields.map((field): ColumnDef<RowData<T>, any> | null => {
@@ -421,9 +425,26 @@ const ValidationTable = <T extends string>({
state: { rowSelection },
enableRowSelection: true,
onRowSelectionChange: setRowSelection,
getRowId: (row) => row.__index || String(row.index)
getRowId: (row) => {
// Prefer __index if available (likely a UUID)
if (row.__index) return row.__index;
// Fall back to position in array
const index = data.indexOf(row);
return String(index);
}
});
// Log selection changes for debugging
useEffect(() => {
const selectedCount = Object.values(rowSelection).filter(v => v === true).length;
const selectedIds = Object.entries(rowSelection)
.filter(([_, selected]) => selected === true)
.map(([id, _]) => id);
console.log(`Row selection updated: ${selectedCount} rows selected, IDs:`, selectedIds);
}, [rowSelection]);
// Don't render if no data
if (data.length === 0) {
return (

View File

@@ -980,6 +980,25 @@ useEffect(() => {
return;
}
console.log(`Applying template ${templateId} to rows:`, rowIndexes);
console.log(`Template data:`, template);
// Validate row indexes
const validRowIndexes = rowIndexes.filter(index =>
index >= 0 && index < data.length && Number.isInteger(index)
);
if (validRowIndexes.length === 0) {
toast.error('No valid rows to update');
console.error('Invalid row indexes:', rowIndexes);
return;
}
if (validRowIndexes.length !== rowIndexes.length) {
console.warn('Some row indexes were invalid and will be skipped:',
rowIndexes.filter(idx => !validRowIndexes.includes(idx)));
}
// Set the template application flag
isApplyingTemplateRef.current = true;
@@ -989,51 +1008,49 @@ useEffect(() => {
top: window.scrollY
};
// Track updated rows
// Track updated rows for UPC validation
const updatedRows: number[] = [];
// Apply template to data - capture the updated data to use for validation
let updatedData: RowData<T>[] = [];
// Create a copy of the data to track updates
const newData = [...data];
setData(prevData => {
const newData = [...prevData];
// Apply template to each valid row
validRowIndexes.forEach(index => {
// Create a new row with template values
const originalRow = newData[index];
console.log(`Applying to row at index ${index}:`, originalRow);
rowIndexes.forEach(index => {
if (index >= 0 && index < newData.length) {
// Create a new row with template values
const updatedRow = { ...newData[index] };
const updatedRow = { ...originalRow };
// Clear existing errors and validation status
delete updatedRow.__errors;
// Clear existing errors
delete updatedRow.__errors;
// Apply template fields (excluding metadata fields)
Object.entries(template).forEach(([key, value]) => {
if (!['id', '__errors', '__meta', '__template', '__original', '__corrected', '__changes'].includes(key)) {
(updatedRow as any)[key] = value;
}
});
// Mark the row as using this template
updatedRow.__template = templateId;
// Update the row in the data array
newData[index] = updatedRow;
// Track which rows were updated
updatedRows.push(index);
// Apply template fields (excluding metadata fields)
Object.entries(template).forEach(([key, value]) => {
if (!['id', '__errors', '__meta', '__template', '__original', '__corrected', '__changes'].includes(key)) {
(updatedRow as any)[key] = value;
}
});
// Store the updated data for validation
updatedData = [...newData];
// Mark the row as using this template
updatedRow.__template = templateId;
return newData;
// Update the row in the data array
newData[index] = updatedRow;
// Track which rows were updated
updatedRows.push(index);
console.log(`Row ${index} updated:`, updatedRow);
});
// Update all data at once
setData(newData);
// Clear validation errors and status for affected rows
setValidationErrors(prev => {
const newErrors = new Map(prev);
rowIndexes.forEach(index => {
validRowIndexes.forEach(index => {
newErrors.delete(index);
});
return newErrors;
@@ -1041,7 +1058,7 @@ useEffect(() => {
setRowValidationStatus(prev => {
const newStatus = new Map(prev);
rowIndexes.forEach(index => {
validRowIndexes.forEach(index => {
newStatus.set(index, 'validated'); // Mark as validated immediately
});
return newStatus;
@@ -1053,10 +1070,10 @@ useEffect(() => {
});
// Show success toast
if (rowIndexes.length === 1) {
if (validRowIndexes.length === 1) {
toast.success('Template applied');
} else if (rowIndexes.length > 1) {
toast.success(`Template applied to ${rowIndexes.length} rows`);
} else if (validRowIndexes.length > 1) {
toast.success(`Template applied to ${validRowIndexes.length} rows`);
}
// Schedule UPC validation with a delay
@@ -1065,7 +1082,7 @@ useEffect(() => {
const processRows = async () => {
for (const rowIndex of updatedRows) {
// Get the current row data after template application
const currentRow = updatedData[rowIndex];
const currentRow = newData[rowIndex];
// Check if UPC validation is needed
if (currentRow && currentRow.upc && currentRow.supplier) {
@@ -1085,7 +1102,7 @@ useEffect(() => {
// Start processing rows
processRows();
}, 500);
}, [templates, validateUpc, setData, setValidationErrors, setRowValidationStatus]);
}, [data, templates, validateUpc, setData, setValidationErrors, setRowValidationStatus]);
// Apply template to selected rows
const applyTemplateToSelected = useCallback((templateId: string) => {
@@ -1097,17 +1114,38 @@ useEffect(() => {
selectedTemplateId: templateId
}));
// Get selected row indexes
const selectedIndexes = Object.keys(rowSelection).map(i => parseInt(i));
// Get selected row keys (which may be UUIDs)
const selectedKeys = Object.entries(rowSelection)
.filter(([_, selected]) => selected === true)
.map(([key, _]) => key);
console.log('Selected row keys:', selectedKeys);
if (selectedKeys.length === 0) {
toast.error('No rows selected');
return;
}
// Map UUID keys to array indices
const selectedIndexes = selectedKeys.map(key => {
// Find the matching row index in the data array
const index = data.findIndex(row =>
(row.__index && row.__index === key) || // Match by __index
(String(data.indexOf(row)) === key) // Or by numeric index
);
return index;
}).filter(index => index !== -1); // Filter out any not found
console.log('Mapped row indices:', selectedIndexes);
if (selectedIndexes.length === 0) {
toast.error('No rows selected');
toast.error('Could not find selected rows');
return;
}
// Apply template to selected rows
applyTemplate(templateId, selectedIndexes);
}, [rowSelection, applyTemplate, setTemplateState]);
}, [rowSelection, applyTemplate, setTemplateState, data]);
// Add field options query
const { data: fieldOptionsData } = useQuery({