Fix creating template from validate table row
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -6,13 +6,14 @@ import { Loader2, X, Plus, Edit3, Sparkles, FileText } from 'lucide-react'
|
|||||||
import { toast } from 'sonner'
|
import { toast } from 'sonner'
|
||||||
import { Switch } from '@/components/ui/switch'
|
import { Switch } from '@/components/ui/switch'
|
||||||
import { useRsi } from '../../../hooks/useRsi'
|
import { useRsi } from '../../../hooks/useRsi'
|
||||||
import { ProductSearchDialog } from '@/components/products/ProductSearchDialog'
|
|
||||||
import SearchableTemplateSelect from './SearchableTemplateSelect'
|
import SearchableTemplateSelect from './SearchableTemplateSelect'
|
||||||
import { useAiValidation } from '../hooks/useAiValidation'
|
import { useAiValidation } from '../hooks/useAiValidation'
|
||||||
import { AiValidationDialogs } from './AiValidationDialogs'
|
import { AiValidationDialogs } from './AiValidationDialogs'
|
||||||
import config from '@/config'
|
import config from '@/config'
|
||||||
import { Fields } from '../../../types'
|
import { Fields } from '../../../types'
|
||||||
import { SearchProductTemplateDialog } from '@/components/templates/SearchProductTemplateDialog'
|
import { SearchProductTemplateDialog } from '@/components/templates/SearchProductTemplateDialog'
|
||||||
|
import { TemplateForm } from '@/components/templates/TemplateForm'
|
||||||
|
import axios from 'axios'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ValidationContainer component - the main wrapper for the validation step
|
* ValidationContainer component - the main wrapper for the validation step
|
||||||
@@ -576,6 +577,143 @@ const ValidationContainer = <T extends string>({
|
|||||||
// State for product search dialog
|
// State for product search dialog
|
||||||
const [isProductSearchDialogOpen, setIsProductSearchDialogOpen] = useState(false)
|
const [isProductSearchDialogOpen, setIsProductSearchDialogOpen] = useState(false)
|
||||||
|
|
||||||
|
// Add new state for template form dialog
|
||||||
|
const [isTemplateFormOpen, setIsTemplateFormOpen] = useState(false)
|
||||||
|
const [templateFormInitialData, setTemplateFormInitialData] = useState<any>(null)
|
||||||
|
const [fieldOptions, setFieldOptions] = useState<any>(null)
|
||||||
|
|
||||||
|
// Function to fetch field options for template form
|
||||||
|
const fetchFieldOptions = useCallback(async () => {
|
||||||
|
try {
|
||||||
|
const response = await axios.get('/api/import/field-options');
|
||||||
|
console.log('Field options from API:', response.data);
|
||||||
|
|
||||||
|
// Check if suppliers are included in the response
|
||||||
|
if (response.data && response.data.suppliers) {
|
||||||
|
console.log('Suppliers available:', response.data.suppliers.length);
|
||||||
|
} else {
|
||||||
|
console.warn('No suppliers found in field options response');
|
||||||
|
}
|
||||||
|
|
||||||
|
setFieldOptions(response.data);
|
||||||
|
return response.data;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching field options:', error);
|
||||||
|
toast.error('Failed to load field options');
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// Function to prepare row data for the template form
|
||||||
|
const prepareRowDataForTemplateForm = useCallback(() => {
|
||||||
|
// Get the selected row key (should be only one)
|
||||||
|
const selectedKey = Object.entries(rowSelection)
|
||||||
|
.filter(([_, selected]) => selected === true)
|
||||||
|
.map(([key, _]) => key)[0];
|
||||||
|
|
||||||
|
if (!selectedKey) return null;
|
||||||
|
|
||||||
|
// Try to find the row in the data array
|
||||||
|
let selectedRow;
|
||||||
|
|
||||||
|
// First check if the key is an index in filteredData
|
||||||
|
const numericIndex = parseInt(selectedKey);
|
||||||
|
if (!isNaN(numericIndex) && numericIndex >= 0 && numericIndex < filteredData.length) {
|
||||||
|
selectedRow = filteredData[numericIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
// If not found by index, try to find it by __index property
|
||||||
|
if (!selectedRow) {
|
||||||
|
selectedRow = data.find(row => row.__index === selectedKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If still not found, return null
|
||||||
|
if (!selectedRow) {
|
||||||
|
console.error('Selected row not found:', selectedKey);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TemplateForm expects supplier as a NUMBER - the field options have numeric values
|
||||||
|
// Convert the supplier to a number if possible
|
||||||
|
let supplierValue;
|
||||||
|
if (selectedRow.supplier) {
|
||||||
|
const numSupplier = Number(selectedRow.supplier);
|
||||||
|
supplierValue = !isNaN(numSupplier) ? numSupplier : selectedRow.supplier;
|
||||||
|
} else {
|
||||||
|
supplierValue = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create template form data with the correctly typed supplier value
|
||||||
|
return {
|
||||||
|
company: selectedRow.company || '',
|
||||||
|
product_type: selectedRow.product_type || '',
|
||||||
|
supplier: supplierValue,
|
||||||
|
msrp: selectedRow.msrp ? Number(Number(selectedRow.msrp).toFixed(2)) : undefined,
|
||||||
|
cost_each: selectedRow.cost_each ? Number(Number(selectedRow.cost_each).toFixed(2)) : undefined,
|
||||||
|
qty_per_unit: selectedRow.qty_per_unit ? Number(selectedRow.qty_per_unit) : undefined,
|
||||||
|
case_qty: selectedRow.case_qty ? Number(selectedRow.case_qty) : undefined,
|
||||||
|
hts_code: selectedRow.hts_code || undefined,
|
||||||
|
description: selectedRow.description || undefined,
|
||||||
|
weight: selectedRow.weight ? Number(Number(selectedRow.weight).toFixed(2)) : undefined,
|
||||||
|
length: selectedRow.length ? Number(Number(selectedRow.length).toFixed(2)) : undefined,
|
||||||
|
width: selectedRow.width ? Number(Number(selectedRow.width).toFixed(2)) : undefined,
|
||||||
|
height: selectedRow.height ? Number(Number(selectedRow.height).toFixed(2)) : undefined,
|
||||||
|
tax_cat: selectedRow.tax_cat ? String(selectedRow.tax_cat) : undefined,
|
||||||
|
size_cat: selectedRow.size_cat ? String(selectedRow.size_cat) : undefined,
|
||||||
|
categories: Array.isArray(selectedRow.categories) ? selectedRow.categories :
|
||||||
|
(selectedRow.categories ? [selectedRow.categories] : []),
|
||||||
|
ship_restrictions: selectedRow.ship_restrictions ? String(selectedRow.ship_restrictions) : undefined
|
||||||
|
};
|
||||||
|
}, [data, filteredData, rowSelection]);
|
||||||
|
|
||||||
|
// Add useEffect to fetch field options when template form opens
|
||||||
|
useEffect(() => {
|
||||||
|
if (isTemplateFormOpen && !fieldOptions) {
|
||||||
|
fetchFieldOptions();
|
||||||
|
}
|
||||||
|
}, [isTemplateFormOpen, fieldOptions, fetchFieldOptions]);
|
||||||
|
|
||||||
|
// Function to handle opening the template form
|
||||||
|
const openTemplateForm = useCallback(async () => {
|
||||||
|
const templateData = prepareRowDataForTemplateForm();
|
||||||
|
if (!templateData) return;
|
||||||
|
|
||||||
|
setTemplateFormInitialData(templateData);
|
||||||
|
|
||||||
|
// Always fetch fresh field options to ensure supplier list is up to date
|
||||||
|
try {
|
||||||
|
const options = await fetchFieldOptions();
|
||||||
|
if (options && options.suppliers) {
|
||||||
|
console.log(`Loaded ${options.suppliers.length} suppliers for template form`);
|
||||||
|
|
||||||
|
// Log if we can find a match for our supplier
|
||||||
|
if (templateData.supplier !== undefined) {
|
||||||
|
// Need to compare numeric values since supplier options have numeric values
|
||||||
|
const supplierMatch = options.suppliers.find(s =>
|
||||||
|
s.value === templateData.supplier ||
|
||||||
|
Number(s.value) === Number(templateData.supplier)
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log('Found supplier match:', supplierMatch ? 'Yes' : 'No',
|
||||||
|
'For supplier value:', templateData.supplier,
|
||||||
|
'Type:', typeof templateData.supplier);
|
||||||
|
|
||||||
|
if (supplierMatch) {
|
||||||
|
console.log('Matched supplier:', supplierMatch.label);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setIsTemplateFormOpen(true);
|
||||||
|
} else {
|
||||||
|
console.error('Failed to load suppliers for template form');
|
||||||
|
toast.error('Could not load supplier options');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error loading field options:', error);
|
||||||
|
toast.error('Failed to prepare template form');
|
||||||
|
}
|
||||||
|
}, [prepareRowDataForTemplateForm, fetchFieldOptions]);
|
||||||
|
|
||||||
// Handle next button click - memoized
|
// Handle next button click - memoized
|
||||||
const handleNext = useCallback(() => {
|
const handleNext = useCallback(() => {
|
||||||
// Make sure any pending item numbers are applied
|
// Make sure any pending item numbers are applied
|
||||||
@@ -864,7 +1002,7 @@ const ValidationContainer = <T extends string>({
|
|||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
size="sm"
|
size="sm"
|
||||||
onClick={() => setIsProductSearchDialogOpen(true)}
|
onClick={openTemplateForm}
|
||||||
>
|
>
|
||||||
Save as Template
|
Save as Template
|
||||||
</Button>
|
</Button>
|
||||||
@@ -956,6 +1094,19 @@ const ValidationContainer = <T extends string>({
|
|||||||
onClose={() => setIsProductSearchDialogOpen(false)}
|
onClose={() => setIsProductSearchDialogOpen(false)}
|
||||||
onTemplateCreated={loadTemplates}
|
onTemplateCreated={loadTemplates}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{/* Template Form Dialog */}
|
||||||
|
<TemplateForm
|
||||||
|
isOpen={isTemplateFormOpen}
|
||||||
|
onClose={() => setIsTemplateFormOpen(false)}
|
||||||
|
onSuccess={() => {
|
||||||
|
loadTemplates();
|
||||||
|
setIsTemplateFormOpen(false);
|
||||||
|
}}
|
||||||
|
initialData={templateFormInitialData}
|
||||||
|
mode="create"
|
||||||
|
fieldOptions={fieldOptions}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user