Move UPC validation table adapter out of ValidationContainer
This commit is contained in:
@@ -0,0 +1,140 @@
|
||||
import React, { useMemo } from 'react'
|
||||
import ValidationTable from './ValidationTable'
|
||||
import { RowSelectionState } from '@tanstack/react-table'
|
||||
import { Fields } from '../../../types'
|
||||
|
||||
interface UpcValidationTableAdapterProps<T extends string> {
|
||||
data: any[]
|
||||
fields: Fields<string>
|
||||
validationErrors: Map<number, Record<string, any[]>>
|
||||
rowSelection: RowSelectionState
|
||||
setRowSelection: (value: RowSelectionState) => void
|
||||
updateRow: (rowIndex: number, key: T, value: any) => void
|
||||
filters: any
|
||||
templates: any[]
|
||||
applyTemplate: (templateId: string, rowIndexes: number[]) => void
|
||||
getTemplateDisplayText: (templateId: string) => string
|
||||
isValidatingUpc: (rowIndex: number) => boolean
|
||||
validatingUpcRows: number[]
|
||||
copyDown: (rowIndex: number, fieldKey: string, endRowIndex?: number) => void
|
||||
validatingCells: Set<string>
|
||||
isLoadingTemplates: boolean
|
||||
rowProductLines: Record<string, any[]>
|
||||
rowSublines: Record<string, any[]>
|
||||
isLoadingLines: Record<string, boolean>
|
||||
isLoadingSublines: Record<string, boolean>
|
||||
upcValidation: {
|
||||
validatingRows: Set<number>
|
||||
getItemNumber: (rowIndex: number) => string | undefined
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* UpcValidationTableAdapter component - connects UPC validation data to ValidationTable
|
||||
*
|
||||
* This component adapts UPC validation data and functionality to work with the core ValidationTable,
|
||||
* transforming item numbers and validation states into a format the table component can render.
|
||||
*/
|
||||
function UpcValidationTableAdapter<T extends string>({
|
||||
data,
|
||||
fields,
|
||||
validationErrors,
|
||||
rowSelection,
|
||||
setRowSelection,
|
||||
updateRow,
|
||||
filters,
|
||||
templates,
|
||||
applyTemplate,
|
||||
getTemplateDisplayText,
|
||||
isValidatingUpc,
|
||||
validatingUpcRows,
|
||||
copyDown,
|
||||
validatingCells: externalValidatingCells,
|
||||
isLoadingTemplates,
|
||||
rowProductLines,
|
||||
rowSublines,
|
||||
isLoadingLines,
|
||||
isLoadingSublines,
|
||||
upcValidation
|
||||
}: UpcValidationTableAdapterProps<T>) {
|
||||
// Prepare the validation table with UPC data
|
||||
const AdaptedTable = useMemo(() => React.memo((props: React.ComponentProps<typeof ValidationTable>) => {
|
||||
// Create validatingCells set from validating rows, but only for item_number fields
|
||||
// This ensures only the item_number column shows loading state during UPC validation
|
||||
const combinedValidatingCells = new Set<string>();
|
||||
|
||||
// Add UPC validation cells
|
||||
upcValidation.validatingRows.forEach(rowIndex => {
|
||||
// Only mark the item_number cells as validating, NOT the UPC or supplier
|
||||
combinedValidatingCells.add(`${rowIndex}-item_number`);
|
||||
});
|
||||
|
||||
// Add any other validating cells from state
|
||||
externalValidatingCells.forEach(cellKey => {
|
||||
combinedValidatingCells.add(cellKey);
|
||||
});
|
||||
|
||||
// Convert the Map to the expected format for the ValidationTable
|
||||
// Create a new Map from the item numbers to ensure proper typing
|
||||
const itemNumbersMap = new Map<number, string>();
|
||||
|
||||
// Merge the item numbers with the data for display purposes only
|
||||
const enhancedData = props.data.map((row: any, index: number) => {
|
||||
const itemNumber = upcValidation.getItemNumber(index);
|
||||
if (itemNumber) {
|
||||
// Add to our map for proper prop passing
|
||||
itemNumbersMap.set(index, itemNumber);
|
||||
|
||||
return {
|
||||
...row,
|
||||
item_number: itemNumber
|
||||
};
|
||||
}
|
||||
return row;
|
||||
});
|
||||
|
||||
return (
|
||||
<ValidationTable
|
||||
{...props}
|
||||
data={enhancedData}
|
||||
validatingCells={combinedValidatingCells}
|
||||
itemNumbers={itemNumbersMap}
|
||||
isLoadingTemplates={isLoadingTemplates}
|
||||
copyDown={copyDown}
|
||||
rowProductLines={rowProductLines}
|
||||
rowSublines={rowSublines}
|
||||
isLoadingLines={isLoadingLines}
|
||||
isLoadingSublines={isLoadingSublines}
|
||||
/>
|
||||
);
|
||||
}), [upcValidation.validatingRows, upcValidation.getItemNumber, isLoadingTemplates, copyDown, externalValidatingCells, rowProductLines, rowSublines, isLoadingLines, isLoadingSublines]);
|
||||
|
||||
// Render the validation table with the provided props and UPC data
|
||||
return (
|
||||
<AdaptedTable
|
||||
data={data}
|
||||
fields={fields}
|
||||
rowSelection={rowSelection}
|
||||
setRowSelection={setRowSelection}
|
||||
updateRow={updateRow as unknown as (rowIndex: number, key: string, value: any) => void}
|
||||
validationErrors={validationErrors}
|
||||
isValidatingUpc={isValidatingUpc}
|
||||
validatingUpcRows={validatingUpcRows}
|
||||
filters={filters}
|
||||
templates={templates}
|
||||
applyTemplate={applyTemplate}
|
||||
getTemplateDisplayText={getTemplateDisplayText}
|
||||
validatingCells={new Set()}
|
||||
itemNumbers={new Map()}
|
||||
isLoadingTemplates={isLoadingTemplates}
|
||||
copyDown={copyDown}
|
||||
upcValidationResults={new Map()}
|
||||
rowProductLines={rowProductLines}
|
||||
rowSublines={rowSublines}
|
||||
isLoadingLines={isLoadingLines}
|
||||
isLoadingSublines={isLoadingSublines}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default UpcValidationTableAdapter
|
||||
@@ -1,6 +1,5 @@
|
||||
import React, { useState, useEffect, useRef, useCallback, useMemo, useLayoutEffect } from 'react'
|
||||
import { useValidationState, Props } from '../hooks/useValidationState'
|
||||
import ValidationTable from './ValidationTable'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Loader2, X, Plus, Edit3, Sparkles, FileText } from 'lucide-react'
|
||||
import { toast } from 'sonner'
|
||||
@@ -9,7 +8,6 @@ import { useRsi } from '../../../hooks/useRsi'
|
||||
import SearchableTemplateSelect from './SearchableTemplateSelect'
|
||||
import { useAiValidation } from '../hooks/useAiValidation'
|
||||
import { AiValidationDialogs } from './AiValidationDialogs'
|
||||
import config from '@/config'
|
||||
import { Fields } from '../../../types'
|
||||
import { SearchProductTemplateDialog } from '@/components/templates/SearchProductTemplateDialog'
|
||||
import { TemplateForm } from '@/components/templates/TemplateForm'
|
||||
@@ -17,6 +15,7 @@ import axios from 'axios'
|
||||
import { RowSelectionState } from '@tanstack/react-table'
|
||||
import { useUpcValidation } from '../hooks/useUpcValidation'
|
||||
import { useProductLinesFetching } from '../hooks/useProductLinesFetching'
|
||||
import UpcValidationTableAdapter from './UpcValidationTableAdapter'
|
||||
|
||||
/**
|
||||
* ValidationContainer component - the main wrapper for the validation step
|
||||
@@ -75,13 +74,12 @@ const ValidationContainer = <T extends string>({
|
||||
const [validatingCells, setValidatingCells] = useState<Set<string>>(new Set());
|
||||
|
||||
// Use UPC validation hook
|
||||
const upcValidation = useUpcValidation<T>(data, setData);
|
||||
const upcValidation = useUpcValidation(data, setData);
|
||||
|
||||
// Function to check if a specific row is being validated - memoized
|
||||
const isRowValidatingUpc = upcValidation.isRowValidatingUpc;
|
||||
|
||||
// Apply all pending updates to the data state
|
||||
const applyItemNumbersToData = upcValidation.applyItemNumbersToData;
|
||||
|
||||
// Use AI validation hook
|
||||
const aiValidation = useAiValidation<T>(
|
||||
@@ -553,99 +551,60 @@ const ValidationContainer = <T extends string>({
|
||||
// No cleanup needed since we're not using a timer
|
||||
}, [data, upcValidation]);
|
||||
|
||||
// Memoize the enhanced validation table component
|
||||
const EnhancedValidationTable = useMemo(() => React.memo((props: React.ComponentProps<typeof ValidationTable>) => {
|
||||
// Create validatingCells set from validating rows, but only for item_number fields
|
||||
// This ensures only the item_number column shows loading state during UPC validation
|
||||
const combinedValidatingCells = new Set<string>();
|
||||
|
||||
// Add UPC validation cells
|
||||
upcValidation.validatingRows.forEach(rowIndex => {
|
||||
// Only mark the item_number cells as validating, NOT the UPC or supplier
|
||||
combinedValidatingCells.add(`${rowIndex}-item_number`);
|
||||
});
|
||||
|
||||
// Add any other validating cells from state
|
||||
validatingCells.forEach(cellKey => {
|
||||
combinedValidatingCells.add(cellKey);
|
||||
});
|
||||
|
||||
// Convert the Map to the expected format for the ValidationTable
|
||||
// Create a new Map from the item numbers to ensure proper typing
|
||||
const itemNumbersMap = new Map<number, string>();
|
||||
|
||||
// Merge the item numbers with the data for display purposes only
|
||||
const enhancedData = props.data.map((row: any, index: number) => {
|
||||
const itemNumber = upcValidation.getItemNumber(index);
|
||||
if (itemNumber) {
|
||||
// Add to our map for proper prop passing
|
||||
itemNumbersMap.set(index, itemNumber);
|
||||
|
||||
return {
|
||||
...row,
|
||||
item_number: itemNumber
|
||||
};
|
||||
// Memoize the rendered validation table
|
||||
const renderValidationTable = useMemo(() => {
|
||||
// Create wrapper for applyTemplate that matches the expected interface
|
||||
const applyTemplateWrapper = (templateId: string, rowIndexes: number[]) => {
|
||||
if (rowIndexes.length === 1) {
|
||||
// Single row apply - pass the array with a single index
|
||||
applyTemplate(templateId, rowIndexes);
|
||||
} else if (rowIndexes.length > 1) {
|
||||
// Multiple rows - use applyTemplateToSelected
|
||||
applyTemplateToSelected(templateId);
|
||||
}
|
||||
return row;
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<ValidationTable
|
||||
{...props}
|
||||
data={enhancedData}
|
||||
validatingCells={combinedValidatingCells}
|
||||
itemNumbers={itemNumbersMap}
|
||||
isLoadingTemplates={isLoadingTemplates}
|
||||
copyDown={handleCopyDown}
|
||||
rowProductLines={rowProductLines}
|
||||
rowSublines={rowSublines}
|
||||
isLoadingLines={isLoadingLines}
|
||||
isLoadingSublines={isLoadingSublines}
|
||||
/>
|
||||
);
|
||||
}), [upcValidation.validatingRows, upcValidation.getItemNumber, isLoadingTemplates, handleCopyDown, validatingCells, rowProductLines, rowSublines, isLoadingLines, isLoadingSublines]);
|
||||
|
||||
// Memoize the rendered validation table
|
||||
const renderValidationTable = useMemo(() => (
|
||||
<EnhancedValidationTable
|
||||
<UpcValidationTableAdapter
|
||||
data={filteredData}
|
||||
fields={fields as unknown as Fields<string>}
|
||||
rowSelection={rowSelection}
|
||||
setRowSelection={handleRowSelectionChange as React.Dispatch<React.SetStateAction<RowSelectionState>>}
|
||||
updateRow={handleUpdateRow as unknown as (rowIndex: number, key: string, value: any) => void}
|
||||
validationErrors={validationErrors}
|
||||
isValidatingUpc={isRowValidatingUpc}
|
||||
validatingUpcRows={Array.from(upcValidation.validatingRows)}
|
||||
rowSelection={rowSelection}
|
||||
setRowSelection={handleRowSelectionChange}
|
||||
updateRow={handleUpdateRow}
|
||||
filters={filters}
|
||||
templates={templates}
|
||||
applyTemplate={applyTemplate}
|
||||
applyTemplate={applyTemplateWrapper}
|
||||
getTemplateDisplayText={getTemplateDisplayText}
|
||||
validatingCells={new Set()}
|
||||
itemNumbers={new Map()}
|
||||
isLoadingTemplates={isLoadingTemplates}
|
||||
isValidatingUpc={isRowValidatingUpc}
|
||||
validatingUpcRows={Array.from(upcValidation.validatingRows)}
|
||||
copyDown={handleCopyDown}
|
||||
upcValidationResults={new Map()}
|
||||
validatingCells={validatingCells}
|
||||
isLoadingTemplates={isLoadingTemplates}
|
||||
rowProductLines={rowProductLines}
|
||||
rowSublines={rowSublines}
|
||||
isLoadingLines={isLoadingLines}
|
||||
isLoadingSublines={isLoadingSublines}
|
||||
upcValidation={upcValidation}
|
||||
/>
|
||||
), [
|
||||
EnhancedValidationTable,
|
||||
);
|
||||
}, [
|
||||
filteredData,
|
||||
fields,
|
||||
validationErrors,
|
||||
rowSelection,
|
||||
handleRowSelectionChange,
|
||||
handleUpdateRow,
|
||||
validationErrors,
|
||||
isRowValidatingUpc,
|
||||
upcValidation.validatingRows,
|
||||
filters,
|
||||
templates,
|
||||
applyTemplate,
|
||||
applyTemplateToSelected,
|
||||
getTemplateDisplayText,
|
||||
isLoadingTemplates,
|
||||
isRowValidatingUpc,
|
||||
upcValidation,
|
||||
handleCopyDown,
|
||||
validatingCells,
|
||||
isLoadingTemplates,
|
||||
rowProductLines,
|
||||
rowSublines,
|
||||
isLoadingLines,
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
import { useState, useCallback, useRef, useEffect } from 'react'
|
||||
import config from '@/config'
|
||||
import { toast } from 'sonner'
|
||||
|
||||
interface UpcValidationResult {
|
||||
error?: boolean
|
||||
message?: string
|
||||
data?: Record<string, any>
|
||||
}
|
||||
|
||||
interface ValidationState {
|
||||
validatingCells: Set<string>; // Using rowIndex-fieldKey as identifier
|
||||
@@ -14,7 +8,7 @@ interface ValidationState {
|
||||
validatingRows: Set<number>; // Rows currently being validated
|
||||
}
|
||||
|
||||
export const useUpcValidation = <T extends string>(
|
||||
export const useUpcValidation = (
|
||||
data: any[],
|
||||
setData: (updater: any[] | ((prevData: any[]) => any[])) => void
|
||||
) => {
|
||||
@@ -158,7 +152,6 @@ export const useUpcValidation = <T extends string>(
|
||||
// Process the response
|
||||
if (response.status === 409) {
|
||||
// UPC already exists - show validation error
|
||||
const errorData = await response.json();
|
||||
return { success: false };
|
||||
} else if (response.ok) {
|
||||
// Successful validation - update item number
|
||||
|
||||
Reference in New Issue
Block a user