From 63159b4b5d5daefc26afc93f760f46d1f455d4aa Mon Sep 17 00:00:00 2001 From: Malini Date: Wed, 19 Nov 2025 10:28:34 +0530 Subject: [PATCH] import bug fix --- .../Admin/configuration/CompanyProfile.jsx | 797 ++++++++++++------ .../Admin/configuration/QuarterlyWindows.jsx | 90 +- 2 files changed, 585 insertions(+), 302 deletions(-) diff --git a/ipi-survey-platform/src/pages/Admin/configuration/CompanyProfile.jsx b/ipi-survey-platform/src/pages/Admin/configuration/CompanyProfile.jsx index 3e90e08..b71ccf8 100644 --- a/ipi-survey-platform/src/pages/Admin/configuration/CompanyProfile.jsx +++ b/ipi-survey-platform/src/pages/Admin/configuration/CompanyProfile.jsx @@ -202,6 +202,258 @@ const createEmptyProfile = () => ({ createdById: '', }); +// Enhanced CSV validation function with detailed error reporting +const validateCSVFile = (file, existingEstablishments = []) => { + return new Promise((resolve, reject) => { + const reader = new FileReader(); + + reader.onload = (e) => { + try { + const csvText = e.target.result; + const lines = csvText.split('\n').filter(line => line.trim() !== ''); + + if (lines.length < 2) { + reject({ + type: 'file_validation', + message: 'CSV file must contain at least a header and one data row', + details: [] + }); + return; + } + + // Parse header + const headers = lines[0].split(',').map(h => h.trim().replace(/"/g, '')); + + // Check required headers + const requiredHeaders = ['Establishment Id', 'Factory Name', 'Email', 'Emirate', 'Total Employment']; + const missingHeaders = requiredHeaders.filter(header => + !headers.some(h => h.toLowerCase() === header.toLowerCase()) + ); + + if (missingHeaders.length > 0) { + reject({ + type: 'header_validation', + message: `Missing required headers: ${missingHeaders.join(', ')}`, + details: missingHeaders.map(header => ({ + header, + message: `Missing required header: ${header}` + })) + }); + return; + } + + const establishmentIdIndex = headers.findIndex(h => + h.toLowerCase().includes('establishment') && h.toLowerCase().includes('id') + ); + const factoryNameIndex = headers.findIndex(h => + h.toLowerCase().includes('factory') && h.toLowerCase().includes('name') + ); + const emailIndex = headers.findIndex(h => h.toLowerCase().includes('email')); + const emirateIndex = headers.findIndex(h => h.toLowerCase() === 'emirate'); + + const errors = []; + const establishmentIds = new Map(); // Track row numbers for each ID + const existingIds = new Set(existingEstablishments.map(est => est.establishmentId)); + const validEmirates = ['Abu Dhabi', 'Dubai', 'Sharjah', 'Ajman', 'Umm Al Quwain', 'Ras Al Khaimah', 'Fujairah']; + + // First pass: collect all establishment IDs to find duplicates + for (let i = 1; i < lines.length; i++) { + const line = lines[i]; + const rowNumber = i + 1; + const values = line.split(',').map(v => v.trim().replace(/"/g, '')); + + // Skip empty rows + if (values.every(v => v === '')) continue; + + if (establishmentIdIndex >= 0 && values[establishmentIdIndex]) { + const establishmentId = values[establishmentIdIndex]; + if (establishmentIds.has(establishmentId)) { + establishmentIds.get(establishmentId).push(rowNumber); + } else { + establishmentIds.set(establishmentId, [rowNumber]); + } + } + } + + // Second pass: validate each row + for (let i = 1; i < lines.length; i++) { + const line = lines[i]; + const rowNumber = i + 1; + const values = line.split(',').map(v => v.trim().replace(/"/g, '')); + + // Skip empty rows + if (values.every(v => v === '')) continue; + + const rowErrors = []; + + // Check Establishment ID + if (establishmentIdIndex >= 0) { + const establishmentId = values[establishmentIdIndex] || ''; + + if (!establishmentId) { + rowErrors.push({ + column: 'Establishment Id', + message: 'Establishment ID is required', + value: '' + }); + } else { + // Check for duplicates within the file + const duplicateRows = establishmentIds.get(establishmentId) || []; + if (duplicateRows.length > 1) { + const otherRows = duplicateRows.filter(r => r !== rowNumber); + rowErrors.push({ + column: 'Establishment Id', + message: `Duplicate ID found in rows: ${otherRows.join(', ')}`, + value: establishmentId, + isDuplicate: true, + duplicateRows: otherRows + }); + } + + // Check against existing establishments + if (existingIds.has(establishmentId)) { + rowErrors.push({ + column: 'Establishment Id', + message: `Establishment ID '${establishmentId}' already exists in the system`, + value: establishmentId, + isSystemDuplicate: true + }); + } + } + } + + // Check Factory Name + if (factoryNameIndex >= 0 && !values[factoryNameIndex]) { + rowErrors.push({ + column: 'Factory Name', + message: 'Factory Name is required', + value: '' + }); + } + + // Check Email + if (emailIndex >= 0) { + const email = values[emailIndex] || ''; + if (!email) { + rowErrors.push({ + column: 'Email', + message: 'Email is required', + value: '' + }); + } else { + const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; + if (!emailRegex.test(email)) { + rowErrors.push({ + column: 'Email', + message: `Invalid email format: ${email}`, + value: email + }); + } + } + } + + // Check Emirate + if (emirateIndex >= 0) { + const emirate = values[emirateIndex] || ''; + if (!emirate) { + rowErrors.push({ + column: 'Emirate', + message: 'Emirate is required', + value: '' + }); + } else if (!validEmirates.some(e => e.toLowerCase() === emirate.toLowerCase())) { + rowErrors.push({ + column: 'Emirate', + message: `Invalid emirate: ${emirate}. Must be one of: ${validEmirates.join(', ')}`, + value: emirate + }); + } + } + + if (rowErrors.length > 0) { + errors.push({ + row: rowNumber, + errors: rowErrors, + data: values + }); + } + } + + if (errors.length > 0) { + // Group errors by type for better reporting + const duplicateErrors = errors.flatMap(row => + row.errors + .filter(e => e.isDuplicate || e.isSystemDuplicate) + .map(error => ({ + ...error, + row: row.row, + data: row.data + })) + ); + + const otherErrors = errors.flatMap(row => + row.errors + .filter(e => !e.isDuplicate && !e.isSystemDuplicate) + .map(error => ({ + ...error, + row: row.row, + data: row.data + })) + ); + + // Create a structured error object + const errorObj = { + type: 'row_validation', + message: `Validation failed for ${errors.length} row(s)`, + details: { + totalErrors: errors.reduce((sum, row) => sum + row.errors.length, 0), + duplicateErrors, + otherErrors, + sampleError: errors[0].errors[0], + sampleRow: errors[0].row + } + }; + + // Customize message based on error types + if (duplicateErrors.length > 0 && otherErrors.length === 0) { + if (duplicateErrors.some(e => e.isSystemDuplicate)) { + errorObj.message = `Found ${duplicateErrors.length} duplicate Establishment ID(s) that already exist in the system`; + } else { + errorObj.message = `Found ${duplicateErrors.length} duplicate Establishment ID(s) in the file`; + } + } else if (otherErrors.length > 0 && duplicateErrors.length === 0) { + errorObj.message = `Found ${otherErrors.length} validation error(s) in the file`; + } + + reject(errorObj); + } else { + resolve({ + isValid: true, + totalRows: lines.length - 1, + headers + }); + } + } catch (error) { + reject({ + type: 'parse_error', + message: `Failed to parse CSV file: ${error.message}`, + details: [] + }); + } + }; + + reader.onerror = () => { + reject({ + type: 'file_error', + message: 'Failed to read file', + details: [] + }); + }; + + reader.readAsText(file); + }); +}; + const CompanyProfile = () => { const navigate = useNavigate(); const [profiles, setProfiles] = React.useState([]); @@ -256,6 +508,7 @@ const CompanyProfile = () => { const [importError, setImportError] = React.useState(''); const fileInputRef = React.useRef(null); const [toastData, setToastData] = React.useState(null); + const [validationResults, setValidationResults] = React.useState(null); // Load current user from session storage React.useEffect(() => { @@ -384,12 +637,13 @@ const CompanyProfile = () => { [form, requiredFieldsByStep] ); - // Fixed Import CSV Functions + // Enhanced Import CSV Functions with Validation const openImportModal = () => { setImportModalOpen(true); setFile(null); setImportError(''); setDragActive(false); + setValidationResults(null); }; const closeImportModal = () => { @@ -397,6 +651,7 @@ const CompanyProfile = () => { setFile(null); setImportError(''); setDragActive(false); + setValidationResults(null); }; const handleDrag = (e) => { @@ -454,6 +709,75 @@ const CompanyProfile = () => { } }, []); + // Enhanced file validation with CSV parsing + const validateFile = async (selectedFile) => { + if (!selectedFile) { + throw new Error("Please select a CSV file to import."); + } + + if (selectedFile.size > 10 * 1024 * 1024) { + throw new Error("File size too large. Please select a file smaller than 10MB."); + } + + const isValidType = selectedFile.type === 'text/csv' || + selectedFile.name.toLowerCase().endsWith('.csv') || + selectedFile.type === 'application/vnd.ms-excel'; + + if (!isValidType) { + throw new Error('Please upload a CSV file only. Supported formats: .csv'); + } + + // Validate CSV content + const existingEstablishmentIds = profiles.map(p => p.establishmentId).filter(id => id); + const validation = await validateCSVFile(selectedFile, existingEstablishmentIds); + + return validation; + }; + + const handleFileChange = async (e) => { + if (e.target.files && e.target.files[0]) { + const selectedFile = e.target.files[0]; + + try { + setImportError(''); + setValidationResults(null); + + const validation = await validateFile(selectedFile); + setFile(selectedFile); + setValidationResults(validation); + + } catch (error) { + setImportError(error.message); + setFile(null); + setValidationResults(null); + } + } + }; + + const handleDrop = async (e) => { + e.preventDefault(); + e.stopPropagation(); + setDragActive(false); + + if (e.dataTransfer.files && e.dataTransfer.files[0]) { + const droppedFile = e.dataTransfer.files[0]; + + try { + setImportError(''); + setValidationResults(null); + + const validation = await validateFile(droppedFile); + setFile(droppedFile); + setValidationResults(validation); + + } catch (error) { + setImportError(error.message); + setFile(null); + setValidationResults(null); + } + } + }; + const renderStepContent = () => { switch (activeStep) { case 0: @@ -1000,10 +1324,7 @@ const CompanyProfile = () => { setProductError(''); setSaveError(''); - setSelectedProducts(prev => { - const updated = prev.filter(p => p.id !== product.id); - return updated; - }); + setSelectedProducts(prev => prev.filter(p => p.id !== product.id)); // Add back to available products if it matches the search term or there's no search term if (!productSearchTerm || @@ -2347,276 +2668,236 @@ const CompanyProfile = () => { return profiles[deletingRow]; }, [deletingRow, profiles]); - const handleImport = async () => { - if (!file) { - const errorMsg = "Please select a CSV file to import."; - setImportError(errorMsg); - setToastData({ - message: errorMsg, - type: "error", - }); - throw new Error(errorMsg); - } - - if (file.size > 10 * 1024 * 1024) { - const errorMsg = "File size too large. Please select a file smaller than 10MB."; - setImportError(errorMsg); - setToastData({ - message: errorMsg, - type: "error", - }); - throw new Error(errorMsg); - } - - try { - setImportLoading(true); - setImportError(""); - - const formData = new FormData(); - formData.append("file", file); - - console.log('FormData entries before upload:'); - for (let pair of formData.entries()) { - console.log(pair[0] + ': ', pair[1]); - } - - let response; - let successMessage = "Company profiles imported successfully!"; - - try { - console.log('Attempting first upload...'); - response = await uploadCompanyProfileCSV(formData); - successMessage = response.message || successMessage; - } catch (firstError) { - console.log('First upload attempt failed, trying alternative:', firstError); - try { - console.log('Attempting alternative upload...'); - response = await uploadCompanyProfileCSVAlternative(formData); - successMessage = response.message || successMessage; - } catch (secondError) { - console.log('Alternative upload also failed:', secondError); - - let detailedErrorMessage = "Upload failed. Please try again."; - let validationErrorCount = 1; // Default count - - // Extract validation error count from response if available - if (secondError.response?.data) { - const responseData = secondError.response.data; - - // Try to extract validation error count from different response structures - if (responseData.validation_errors) { - validationErrorCount = responseData.validation_errors.length || 1; - } else if (responseData.errors) { - validationErrorCount = responseData.errors.length || 1; - } else if (responseData.details && Array.isArray(responseData.details)) { - validationErrorCount = responseData.details.length || 1; - } else if (typeof responseData === 'string') { - // Try to extract count from error message - const countMatch = responseData.match(/(\d+)\s*validation errors?/i); - if (countMatch) { - validationErrorCount = parseInt(countMatch[1]) || 1; - } - } - } - - if (secondError.response?.data?.message) { - detailedErrorMessage = secondError.response.data.message; - } else if (secondError.message) { - if (secondError.message.includes("Request failed with status code")) { - if (secondError.response?.data) { - const responseData = secondError.response.data; - if (typeof responseData === 'string' && responseData.includes("Duplicate Establishment IDs")) { - detailedErrorMessage = responseData; - } else if (responseData.error) { - detailedErrorMessage = responseData.error; - } else if (responseData.details) { - detailedErrorMessage = responseData.details; - } else { - detailedErrorMessage = "Data already exists in the system. Please remove or update the duplicate entries and try again."; - } - } else { - detailedErrorMessage = "Server error occurred during upload. Please try again."; - } - } else { - detailedErrorMessage = secondError.message; - } - } - - // Enhanced validation error detection with dynamic count - if (detailedErrorMessage.includes("No file uploaded") || - detailedErrorMessage.includes("No file found")) { - detailedErrorMessage = "Please select a valid CSV file to upload."; - } else if (detailedErrorMessage.includes("token") || - detailedErrorMessage.includes("auth") || - detailedErrorMessage.includes("Authentication")) { - detailedErrorMessage = "Authentication failed. Please check your login credentials."; - } else if (detailedErrorMessage.includes("400") || - detailedErrorMessage.includes("Bad Request")) { - detailedErrorMessage = "Invalid file format or missing required data. Please check your CSV file."; - } else if (detailedErrorMessage.includes("Duplicate Establishment IDs") || - detailedErrorMessage.includes("duplicate") || - detailedErrorMessage.includes("already exist")) { - detailedErrorMessage = "Duplicate Establishment IDs found (in file or already exist in system). Resolve and re-upload."; - } else if (detailedErrorMessage.includes("validation error") || - detailedErrorMessage.includes("validation errors") || - detailedErrorMessage.includes("No establishments imported") || - detailedErrorMessage.includes("HS Codes do not exist") || - detailedErrorMessage.includes("HS Code")) { - // Format validation error with dynamic count and HS code message -detailedErrorMessage = `Import failed. ${validationErrorCount} HS Codes in your file do not exist in the Product Master. Please use the correct HS Code and try again.`; - } - - throw new Error(detailedErrorMessage); - } - } - - // Check if the response indicates validation errors - if (response && (response.message?.includes("validation error") || - response.message?.includes("validation errors") || - response.message?.includes("No establishments imported") || - response.message?.includes("HS Codes do not exist") || - response.message?.includes("HS Code"))) { - - let validationErrorCount = 1; - // Extract count from response if available - if (response.validation_errors) { - validationErrorCount = response.validation_errors.length || 1; - } else if (response.errors) { - validationErrorCount = response.errors.length || 1; - } - -const validationErrorMessage = `Import failed. ${validationErrorCount} HS Codes in your file do not exist in the Product Master. Please use the correct HS Code and try again.`; - - // Show validation error in red - setImportError(validationErrorMessage); + // Enhanced Import Function with Validation + const handleImport = async () => { + if (!file) { + const errorMsg = "Please select a CSV file to import."; + setImportError(errorMsg); setToastData({ - message: validationErrorMessage, + message: errorMsg, type: "error", }); - throw new Error(validationErrorMessage); + throw new Error(errorMsg); } - setToastData({ - message: successMessage, - type: "success", - }); - - closeImportModal(); - try { - setIsLoading(true); - const res = await fetchEstablishments(); - const payload = res?.data ?? res; - const records = Array.isArray(payload?.data) - ? payload.data - : Array.isArray(payload) - ? payload - : []; + setImportLoading(true); + setImportError(""); - setProfiles(records.map(mapApiEstablishmentToProfile)); - setTotalItems(records.length); - } catch (refreshErr) { - console.log("Error refreshing data:", refreshErr); - } finally { - setIsLoading(false); - } + // Re-validate file before upload + await validateFile(file); - return response; + const formData = new FormData(); + formData.append("file", file); - } catch (error) { - console.error("Error importing CSV:", error); + console.log('FormData entries before upload:'); + for (let pair of formData.entries()) { + console.log(pair[0] + ': ', pair[1]); + } - let errorMessage = error.message || "Upload failed. Please try again."; + let response; + let successMessage = "Company profiles imported successfully!"; - if (errorMessage.includes("Request failed with status code")) { - const parts = errorMessage.split("Request failed with status code"); - if (parts.length > 1) { - const actualError = parts[1].replace(/^\d+\s*/, '').trim(); - if (actualError && actualError.length > 0) { - errorMessage = actualError; - } else { - errorMessage = "Server error occurred. Please try again."; + try { + console.log('Attempting first upload...'); + response = await uploadCompanyProfileCSV(formData); + successMessage = response.message || successMessage; + } catch (firstError) { + console.log('First upload attempt failed, trying alternative:', firstError); + try { + console.log('Attempting alternative upload...'); + response = await uploadCompanyProfileCSVAlternative(formData); + successMessage = response.message || successMessage; + } catch (secondError) { + console.log('Alternative upload also failed:', secondError); + + let detailedErrorMessage = "Upload failed. Please try again."; + let validationErrorCount = 1; // Default count + + // Extract validation error count from response if available + if (secondError.response?.data) { + const responseData = secondError.response.data; + + // Try to extract validation error count from different response structures + if (responseData.validation_errors) { + validationErrorCount = responseData.validation_errors.length || 1; + } else if (responseData.errors) { + validationErrorCount = responseData.errors.length || 1; + } else if (responseData.details && Array.isArray(responseData.details)) { + validationErrorCount = responseData.details.length || 1; + } else if (typeof responseData === 'string') { + // Try to extract count from error message + const countMatch = responseData.match(/(\d+)\s*validation errors?/i); + if (countMatch) { + validationErrorCount = parseInt(countMatch[1]) || 1; + } + } + } + + if (secondError.response?.data?.message) { + detailedErrorMessage = secondError.response.data.message; + } else if (secondError.message) { + if (secondError.message.includes("Request failed with status code")) { + if (secondError.response?.data) { + const responseData = secondError.response.data; + if (typeof responseData === 'string' && responseData.includes("Duplicate Establishment IDs")) { + detailedErrorMessage = responseData; + } else if (responseData.error) { + detailedErrorMessage = responseData.error; + } else if (responseData.details) { + detailedErrorMessage = responseData.details; + } else { + detailedErrorMessage = "Data already exists in the system. Please remove or update the duplicate entries and try again."; + } + } else { + detailedErrorMessage = "Server error occurred during upload. Please try again."; + } + } else { + detailedErrorMessage = secondError.message; + } + } + + // Enhanced validation error detection with dynamic count + if (detailedErrorMessage.includes("No file uploaded") || + detailedErrorMessage.includes("No file found")) { + detailedErrorMessage = "Please select a valid CSV file to upload."; + } else if (detailedErrorMessage.includes("token") || + detailedErrorMessage.includes("auth") || + detailedErrorMessage.includes("Authentication")) { + detailedErrorMessage = "Authentication failed. Please check your login credentials."; + } else if (detailedErrorMessage.includes("400") || + detailedErrorMessage.includes("Bad Request")) { + detailedErrorMessage = "Invalid file format or missing required data. Please check your CSV file."; + } else if (detailedErrorMessage.includes("Duplicate Establishment IDs") || + detailedErrorMessage.includes("duplicate") || + detailedErrorMessage.includes("already exist")) { + detailedErrorMessage = "Duplicate Establishment IDs found (in file or already exist in system). Resolve and re-upload."; + } else if (detailedErrorMessage.includes("validation error") || + detailedErrorMessage.includes("validation errors") || + detailedErrorMessage.includes("No establishments imported") || + detailedErrorMessage.includes("HS Codes do not exist") || + detailedErrorMessage.includes("HS Code")) { + // Format validation error with dynamic count and HS code message + detailedErrorMessage = `Import failed. ${validationErrorCount} HS Codes in your file do not exist in the Product Master. Please use the correct HS Code and try again.`; + } + + throw new Error(detailedErrorMessage); } } - } - // Enhanced error message handling for validation errors with dynamic count - if (errorMessage.includes("expired") || errorMessage.includes("Authentication")) { - errorMessage = "Authentication failed. Please check your login credentials."; - } - - if (errorMessage.includes("Duplicate Establishment IDs") || - errorMessage.includes("duplicate") || - errorMessage.includes("already exist")) { - errorMessage = "Duplicate Establishment IDs found (in file or already exist in system). Resolve and re-upload."; - } - - if (errorMessage.includes("validation error") || - errorMessage.includes("validation errors") || - errorMessage.includes("No establishments imported") || - errorMessage.includes("HS Codes do not exist") || - errorMessage.includes("HS Code")) { - - let validationErrorCount = 1; - // Try to extract count from existing error message - const countMatch = errorMessage.match(/(\d+)\s*validation errors?/i); - if (countMatch) { - validationErrorCount = parseInt(countMatch[1]) || 1; + // Check if the response indicates validation errors + if (response && (response.message?.includes("validation error") || + response.message?.includes("validation errors") || + response.message?.includes("No establishments imported") || + response.message?.includes("HS Codes do not exist") || + response.message?.includes("HS Code"))) { + + let validationErrorCount = 1; + // Extract count from response if available + if (response.validation_errors) { + validationErrorCount = response.validation_errors.length || 1; + } else if (response.errors) { + validationErrorCount = response.errors.length || 1; + } + + const validationErrorMessage = `Import failed. ${validationErrorCount} HS Codes in your file do not exist in the Product Master. Please use the correct HS Code and try again.`; + + // Show validation error in red + setImportError(validationErrorMessage); + setToastData({ + message: validationErrorMessage, + type: "error", + }); + throw new Error(validationErrorMessage); } - -errorMessage = `Import failed. ${validationErrorCount} HS Code${validationErrorCount > 1 ? "s" : ""} in your file ${validationErrorCount > 1 ? "do" : "does"} not exist in the Product Master. Please use the correct HS Code${validationErrorCount > 1 ? "s" : ""} and try again.`; - } - setImportError(errorMessage); + // Show success message + setToastData({ + message: successMessage, + type: "success", + }); - setToastData({ - message: errorMessage, - type: "error", - }); + closeImportModal(); + setImportLoading(true); // Show loader while refreshing data - throw error; + try { + // Refresh the data + const res = await fetchEstablishments(); + const payload = res?.data ?? res; + const records = Array.isArray(payload?.data) + ? payload.data + : Array.isArray(payload) + ? payload + : []; - } finally { - setImportLoading(false); - } -}; - - const handleFileChange = (e) => { - if (e.target.files && e.target.files[0]) { - const selectedFile = e.target.files[0]; - - const isValidType = selectedFile.type === 'text/csv' || - selectedFile.name.toLowerCase().endsWith('.csv') || - selectedFile.type === 'application/vnd.ms-excel'; - - if (isValidType) { - setFile(selectedFile); - setImportError(''); - } else { - setImportError('Please upload a CSV file only. Supported formats: .csv'); - setFile(null); + setProfiles(records.map(mapApiEstablishmentToProfile)); + setTotalItems(records.length); + + // Refresh the page immediately + window.location.reload(); + } catch (refreshErr) { + console.log("Error refreshing data:", refreshErr); + } finally { + setIsLoading(false); } - } - }; - const handleDrop = (e) => { - e.preventDefault(); - e.stopPropagation(); - setDragActive(false); + return response; - if (e.dataTransfer.files && e.dataTransfer.files[0]) { - const droppedFile = e.dataTransfer.files[0]; - - const isValidType = droppedFile.type === 'text/csv' || - droppedFile.name.toLowerCase().endsWith('.csv') || - droppedFile.type === 'application/vnd.ms-excel'; - - if (isValidType) { - setFile(droppedFile); - setImportError(''); - } else { - setImportError('Please upload a CSV file only. Supported formats: .csv'); + } catch (error) { + console.error("Error importing CSV:", error); + + let errorMessage = error.message || "Upload failed. Please try again."; + + if (errorMessage.includes("Request failed with status code")) { + const parts = errorMessage.split("Request failed with status code"); + if (parts.length > 1) { + const actualError = parts[1].replace(/^\d+\s*/, '').trim(); + if (actualError && actualError.length > 0) { + errorMessage = actualError; + } else { + errorMessage = "Server error occurred. Please try again."; + } + } } + + // Enhanced error message handling for validation errors with dynamic count + if (errorMessage.includes("expired") || errorMessage.includes("Authentication")) { + errorMessage = "Authentication failed. Please check your login credentials."; + } + + if (errorMessage.includes("Duplicate Establishment IDs") || + errorMessage.includes("duplicate") || + errorMessage.includes("already exist")) { + errorMessage = "Duplicate Establishment IDs found (in file or already exist in system). Resolve and re-upload."; + } + + if (errorMessage.includes("validation error") || + errorMessage.includes("validation errors") || + errorMessage.includes("No establishments imported") || + errorMessage.includes("HS Codes do not exist") || + errorMessage.includes("HS Code")) { + + let validationErrorCount = 1; + // Try to extract count from existing error message + const countMatch = errorMessage.match(/(\d+)\s*validation errors?/i); + if (countMatch) { + validationErrorCount = parseInt(countMatch[1]) || 1; + } + + errorMessage = `Import failed. ${validationErrorCount} HS Code${validationErrorCount > 1 ? "s" : ""} in your file ${validationErrorCount > 1 ? "do" : "does"} not exist in the Product Master. Please use the correct HS Code${validationErrorCount > 1 ? "s" : ""} and try again.`; + } + + setImportError(errorMessage); + + setToastData({ + message: errorMessage, + type: "error", + }); + + throw error; + + } finally { + setImportLoading(false); } }; @@ -2675,7 +2956,7 @@ errorMessage = `Import failed. ${validationErrorCount} HS Code${validationErrorC
-
+
Import Import CSV @@ -3058,9 +3339,9 @@ errorMessage = `Import failed. ${validationErrorCount} HS Code${validationErrorC

Supports .csv files only (Max 10MB)

- {file && ( + {file && validationResults && (

- ✓ File selected and ready to import + ✓ File validated successfully - {validationResults.totalRows} rows ready to import

)}
@@ -3120,9 +3401,9 @@ errorMessage = `Import failed. ${validationErrorCount} HS Code${validationErrorC
-
- { - if (colIndex === headers.length - 1) { - return ( -
- -
- ); - } - return value; - }} - pagination={{ - currentPage, - onPageChange: (page) => { - setCurrentPage(page); - window.scrollTo({ top: 0, behavior: 'smooth' }); - }, - pageSize, - totalItems: filteredRows.length, - pageSizeOptions: [10, 20, 50, 100], - onPageSizeChange: (size) => { - setPageSize(size); - setCurrentPage(1); - } - }} - /> +
+
+
{ + if (colIndex === headers.length - 1) { + return ( +
+ +
+ ); + } + return value; + }} + pagination={{ + currentPage, + onPageChange: (page) => { + setCurrentPage(page); + window.scrollTo({ top: 0, behavior: 'smooth' }); + }, + pageSize, + totalItems: filteredRows.length, + pageSizeOptions: [10, 20, 50, 100], + onPageSizeChange: (size) => { + setPageSize(size); + setCurrentPage(1); + } + }} + /> + {modalMode && (