Fix upc validation api call
This commit is contained in:
@@ -37,38 +37,6 @@ const ValidationIcon = React.memo(({ error }: { error: ErrorObject }) => (
|
|||||||
|
|
||||||
ValidationIcon.displayName = 'ValidationIcon';
|
ValidationIcon.displayName = 'ValidationIcon';
|
||||||
|
|
||||||
// Separate component for item number cells to ensure they update independently
|
|
||||||
const ItemNumberCell = React.memo(({
|
|
||||||
value,
|
|
||||||
itemNumber,
|
|
||||||
isValidating,
|
|
||||||
width
|
|
||||||
}: {
|
|
||||||
value: any,
|
|
||||||
itemNumber?: string,
|
|
||||||
isValidating?: boolean,
|
|
||||||
width: number
|
|
||||||
}) => (
|
|
||||||
<TableCell className="p-1" style={{ width: `${width}px`, minWidth: `${width}px` }}>
|
|
||||||
<div className="px-2 py-1 text-sm">
|
|
||||||
{isValidating ? (
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
<Loader2 className="h-4 w-4 animate-spin text-blue-500" />
|
|
||||||
<span>{itemNumber || value || ''}</span>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<span>{itemNumber || value || ''}</span>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</TableCell>
|
|
||||||
), (prev, next) => (
|
|
||||||
prev.value === next.value &&
|
|
||||||
prev.itemNumber === next.itemNumber &&
|
|
||||||
prev.isValidating === next.isValidating
|
|
||||||
));
|
|
||||||
|
|
||||||
ItemNumberCell.displayName = 'ItemNumberCell';
|
|
||||||
|
|
||||||
// Memoized base cell content component
|
// Memoized base cell content component
|
||||||
const BaseCellContent = React.memo(({
|
const BaseCellContent = React.memo(({
|
||||||
field,
|
field,
|
||||||
@@ -143,6 +111,66 @@ export interface ValidationCellProps {
|
|||||||
rowIndex: number
|
rowIndex: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ItemNumberCell = React.memo(({
|
||||||
|
value,
|
||||||
|
itemNumber,
|
||||||
|
isValidating,
|
||||||
|
width,
|
||||||
|
errors = [],
|
||||||
|
field,
|
||||||
|
onChange
|
||||||
|
}: {
|
||||||
|
value: any,
|
||||||
|
itemNumber?: string,
|
||||||
|
isValidating?: boolean,
|
||||||
|
width: number,
|
||||||
|
errors?: ErrorObject[],
|
||||||
|
field: Field<string>,
|
||||||
|
onChange: (value: any) => void
|
||||||
|
}) => {
|
||||||
|
const hasError = errors.some(error => error.level === 'error' || error.level === 'warning');
|
||||||
|
const isRequiredButEmpty = errors.some(error => error.level === 'required' && (!value || value.trim() === ''));
|
||||||
|
const nonRequiredErrors = errors.filter(error => error.level !== 'required');
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TableCell className="p-1" style={{ width: `${width}px`, minWidth: `${width}px` }}>
|
||||||
|
<div className={`relative ${hasError || isRequiredButEmpty ? 'border-red-500' : ''}`}>
|
||||||
|
{isValidating ? (
|
||||||
|
<div className="flex items-center justify-center gap-2">
|
||||||
|
<Loader2 className="h-4 w-4 animate-spin text-blue-500" />
|
||||||
|
<span>{itemNumber || value || ''}</span>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="truncate overflow-hidden">
|
||||||
|
<BaseCellContent
|
||||||
|
field={field}
|
||||||
|
value={itemNumber || value}
|
||||||
|
onChange={onChange}
|
||||||
|
hasErrors={hasError || isRequiredButEmpty}
|
||||||
|
options={[]}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{nonRequiredErrors.length > 0 && !isRequiredButEmpty && (
|
||||||
|
<div className="absolute right-2 top-1/2 -translate-y-1/2 z-20">
|
||||||
|
<ValidationIcon error={{
|
||||||
|
message: nonRequiredErrors.map(e => e.message).join('\n'),
|
||||||
|
level: 'error'
|
||||||
|
}} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</TableCell>
|
||||||
|
);
|
||||||
|
}, (prev, next) => (
|
||||||
|
prev.value === next.value &&
|
||||||
|
prev.itemNumber === next.itemNumber &&
|
||||||
|
prev.isValidating === next.isValidating &&
|
||||||
|
JSON.stringify(prev.errors) === JSON.stringify(next.errors)
|
||||||
|
));
|
||||||
|
|
||||||
|
ItemNumberCell.displayName = 'ItemNumberCell';
|
||||||
|
|
||||||
const ValidationCell = ({
|
const ValidationCell = ({
|
||||||
field,
|
field,
|
||||||
value,
|
value,
|
||||||
@@ -161,14 +189,13 @@ const ValidationCell = ({
|
|||||||
itemNumber={itemNumber}
|
itemNumber={itemNumber}
|
||||||
isValidating={isValidating}
|
isValidating={isValidating}
|
||||||
width={width}
|
width={width}
|
||||||
|
errors={errors}
|
||||||
|
field={field}
|
||||||
|
onChange={onChange}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// For UPC fields, show loading indicator during validation
|
|
||||||
const isUpcField = fieldKey === 'upc' || fieldKey === 'barcode';
|
|
||||||
const showLoadingIndicator = isUpcField && isValidating;
|
|
||||||
|
|
||||||
// Error states
|
// Error states
|
||||||
const hasError = errors.some(error => error.level === 'error' || error.level === 'warning');
|
const hasError = errors.some(error => error.level === 'error' || error.level === 'warning');
|
||||||
const isRequiredButEmpty = errors.some(error => error.level === 'required' && (!value || value.trim() === ''));
|
const isRequiredButEmpty = errors.some(error => error.level === 'required' && (!value || value.trim() === ''));
|
||||||
@@ -176,12 +203,8 @@ const ValidationCell = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<TableCell className="p-1" style={{ width: `${width}px`, minWidth: `${width}px` }}>
|
<TableCell className="p-1" style={{ width: `${width}px`, minWidth: `${width}px` }}>
|
||||||
<div className={`relative ${hasError || isRequiredButEmpty ? 'border-red-500' : ''} ${showLoadingIndicator ? 'border-blue-500' : ''}`}>
|
<div className={`relative ${hasError || isRequiredButEmpty ? 'border-red-500' : ''}`}>
|
||||||
{showLoadingIndicator && (
|
|
||||||
<div className="absolute right-2 top-1/2 -translate-y-1/2 z-10">
|
|
||||||
<Loader2 className="h-4 w-4 animate-spin text-blue-500" />
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<div className="truncate overflow-hidden">
|
<div className="truncate overflow-hidden">
|
||||||
<BaseCellContent
|
<BaseCellContent
|
||||||
@@ -220,15 +243,6 @@ export default React.memo(ValidationCell, (prev, next) => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// For UPC fields, include validation state in comparison
|
|
||||||
if (prev.fieldKey === 'upc' || prev.fieldKey === 'barcode') {
|
|
||||||
return (
|
|
||||||
prev.value === next.value &&
|
|
||||||
prevErrorsStr === nextErrorsStr &&
|
|
||||||
prev.isValidating === next.isValidating
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// For all other fields, compare core props
|
// For all other fields, compare core props
|
||||||
return (
|
return (
|
||||||
prev.value === next.value &&
|
prev.value === next.value &&
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ 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'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ValidationContainer component - the main wrapper for the validation step
|
* ValidationContainer component - the main wrapper for the validation step
|
||||||
@@ -187,7 +188,7 @@ const ValidationContainer = <T extends string>({
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Make API call to validate UPC
|
// Make API call to validate UPC
|
||||||
const response = await fetch(`/api/import/check-upc-and-generate-sku?upc=${encodeURIComponent(upcValue)}&supplierId=${encodeURIComponent(supplierId)}`);
|
const response = await fetch(`${config.apiUrl}/import/check-upc-and-generate-sku?upc=${encodeURIComponent(upcValue)}&supplierId=${encodeURIComponent(supplierId)}`);
|
||||||
|
|
||||||
// Process the response
|
// Process the response
|
||||||
if (response.status === 409) {
|
if (response.status === 409) {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { useState, useCallback, useRef } from 'react'
|
import { useState, useCallback, useRef } from 'react'
|
||||||
|
import config from '@/config'
|
||||||
|
|
||||||
interface UpcValidationResult {
|
interface UpcValidationResult {
|
||||||
error?: boolean
|
error?: boolean
|
||||||
@@ -67,7 +68,7 @@ export const useUpcValidation = () => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// Call the UPC validation API
|
// Call the UPC validation API
|
||||||
const response = await fetch(`/api/import/check-upc-and-generate-sku?upc=${encodeURIComponent(upcValue)}&supplierId=${encodeURIComponent(supplier)}`);
|
const response = await fetch(`${config.apiUrl}/import/check-upc-and-generate-sku?upc=${encodeURIComponent(upcValue)}&supplierId=${encodeURIComponent(supplier)}`);
|
||||||
|
|
||||||
if (response.status === 409) {
|
if (response.status === 409) {
|
||||||
const errorData = await response.json();
|
const errorData = await response.json();
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ declare global {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Use a helper to get API URL consistently
|
// Use a helper to get API URL consistently
|
||||||
export const getApiUrl = () => window.config?.apiUrl || '/api';
|
export const getApiUrl = () => config.apiUrl;
|
||||||
|
|
||||||
// Main validation state hook
|
// Main validation state hook
|
||||||
export const useValidationState = <T extends string>({
|
export const useValidationState = <T extends string>({
|
||||||
@@ -125,7 +125,7 @@ export const useValidationState = <T extends string>({
|
|||||||
const fetchProductByUpc = useCallback(async (supplier: string, upc: string): Promise<ValidationResult> => {
|
const fetchProductByUpc = useCallback(async (supplier: string, upc: string): Promise<ValidationResult> => {
|
||||||
try {
|
try {
|
||||||
// Use the correct endpoint and parameter names
|
// Use the correct endpoint and parameter names
|
||||||
const response = await fetch(`${getApiUrl()}/check-upc-and-generate-sku?supplierId=${encodeURIComponent(supplier)}&upc=${encodeURIComponent(upc)}`, {
|
const response = await fetch(`${getApiUrl()}/import/check-upc-and-generate-sku?supplierId=${encodeURIComponent(supplier)}&upc=${encodeURIComponent(upc)}`, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
@@ -224,7 +224,7 @@ export const useValidationState = <T extends string>({
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Make API call to validate UPC
|
// Make API call to validate UPC
|
||||||
const response = await fetch(`/api/import/check-upc-and-generate-sku?upc=${encodeURIComponent(upcValue)}&supplierId=${encodeURIComponent(supplierId)}`);
|
const response = await fetch(`${config.apiUrl}/import/check-upc-and-generate-sku?upc=${encodeURIComponent(upcValue)}&supplierId=${encodeURIComponent(supplierId)}`);
|
||||||
|
|
||||||
if (response.status === 409) {
|
if (response.status === 409) {
|
||||||
// UPC already exists - show validation error
|
// UPC already exists - show validation error
|
||||||
|
|||||||
Reference in New Issue
Block a user