// Simulated vendor configuration data const vendorConfig = [ {"Vendor_Carrier": "Lenovo", "Method": "Pallet", "CUSTPONBR": "Customer PO", "SKU": "Product ID", "SHIPQTY": "Product Quantity", "PACKAGEID": "Pallet ID"}, {"Vendor_Carrier": "HP", "Method": "Pallet", "CUSTPONBR": "PO", "SKU": "VPN", "SHIPQTY": "UNITS", "PACKAGEID": "PACKAHE"}, {"Vendor_Carrier": "Microsoft", "Method": "VPN", "CUSTPONBR": "PONum", "SKU": "PARTID", "SHIPQTY": "SHPQTY", "PACKAGEID": "PARTID"} ]; // DOM Elements const vendorSelect = document.getElementById('vendor-select'); const fileInput = document.getElementById('file-input'); const dropZone = document.getElementById('drop-zone'); const fileInfo = document.getElementById('file-info'); const fileName = document.getElementById('file-name'); const processBtn = document.getElementById('process-btn'); const resultsContainer = document.getElementById('results-container'); const errorContainer = document.getElementById('error-container'); const errorMessage = document.getElementById('error-message'); const jobInfo = document.getElementById('job-info'); const timestampEl = document.getElementById('timestamp'); const headerRowEl = document.getElementById('header-row'); const columnIndicesEl = document.getElementById('column-indices'); const resultsTableBody = document.querySelector('#results-table tbody'); const downloadBtn = document.getElementById('download-btn'); let currentFile = null; let transformedData = []; // Initialize vendor dropdown function initVendorDropdown() { vendorConfig.forEach(vendor => { const option = document.createElement('option'); option.value = vendor.Vendor_Carrier; option.textContent = vendor.Vendor_Carrier; vendorSelect.appendChild(option); }); } // Handle file selection function handleFileSelection(file) { if (!file) return; const validTypes = ['application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/vnd.ms-excel', 'text/csv', 'text/plain']; if (!validTypes.includes(file.type)) { showError('Invalid file type. Please upload an Excel or CSV file.'); return; } currentFile = file; fileName.textContent = file.name; fileInfo.classList.remove('hidden'); processBtn.disabled = false; } // Drag and drop handlers ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => { dropZone.addEventListener(eventName, preventDefaults, false); }); function preventDefaults(e) { e.preventDefault(); e.stopPropagation(); } ['dragenter', 'dragover'].forEach(eventName => { dropZone.addEventListener(eventName, highlight, false); }); ['dragleave', 'drop'].forEach(eventName => { dropZone.addEventListener(eventName, unhighlight, false); }); function highlight() { dropZone.classList.add('dragover'); } function unhighlight() { dropZone.classList.remove('dragover'); } dropZone.addEventListener('drop', handleDrop, false); function handleDrop(e) { const dt = e.dataTransfer; const file = dt.files[0]; handleFileSelection(file); } // Click on drop zone triggers file input dropZone.addEventListener('click', () => { fileInput.click(); }); fileInput.addEventListener('change', (e) => { handleFileSelection(e.target.files[0]); }); // Process file button handler processBtn.addEventListener('click', processFile); // Download CSV handler downloadBtn.addEventListener('click', downloadCSV); // Initialize the app initVendorDropdown(); // Main processing function async function processFile() { if (!currentFile || !vendorSelect.value) { showError('Please select a vendor and upload a file.'); return; } // Show loading state processBtn.disabled = true; processBtn.innerHTML = 'Processing...'; feather.replace(); try { // In a real app, this would be an API call to the backend // For this demo, we'll simulate the processing await new Promise(resolve => setTimeout(resolve, 1500)); // Get selected vendor config const vendor = vendorConfig.find(v => v.Vendor_Carrier === vendorSelect.value); if (!vendor) throw new Error('Vendor configuration not found'); // Simulate data transformation const result = simulateDataTransformation(vendor); // Display results displayResults(result.data, result.jobInfo); } catch (error) { showError(error.message); } finally { processBtn.disabled = false; processBtn.innerHTML = 'Process File'; feather.replace(); } } // Simulate data transformation (in a real app, this would be server-side) function simulateDataTransformation(vendorConfig) { // Build mapping dictionary const mapping = {}; const requiredHeaders = []; ['CUSTPONBR', 'SKU', 'SHIPQTY', 'PACKAGEID'].forEach(internal => { const external = vendorConfig[internal]; if (external && external.trim() !== '') { mapping[external] = internal; requiredHeaders.push(external); } }); // Simulate finding header row (in a real app, this would parse the file) const headerRowIndex = Math.floor(Math.random() * 3); // Random row 0-2 // Validate headers (simulated) const missingHeaders = []; const foundHeaders = Object.keys(mapping); requiredHeaders.forEach(header => { if (!foundHeaders.includes(header)) { missingHeaders.push(header); } }); if (missingHeaders.length > 0) { throw new Error(`Missing required headers: ${missingHeaders.join(', ')}`); } // Simulate transformed data const data = []; const rowCount = 5 + Math.floor(Math.random() * 10); for (let i = 0; i < rowCount; i++) { data.push({ CUSTPONBR: `PO-${Math.floor(Math.random() * 10000)}`, SKU: `SKU-${Math.floor(Math.random() * 1000)}`, SHIPQTY: Math.floor(Math.random() * 100), PACKAGEID: `PKG-${Math.floor(Math.random() * 100)}` }); } // Generate job info const now = new Date(); const jobInfo = { timestamp: now.toISOString().replace('T', ' ').substring(0, 19), headerRow: headerRowIndex, columnIndices: generateColumnIndices(Object.keys(mapping).length) }; return { data, jobInfo }; } // Generate fake column indices (A, B, C, etc.) function generateColumnIndices(count) { const indices = []; for (let i = 0; i < count; i++) { indices.push(String.fromCharCode(65 + i)); // ASCII 'A' is 65 } return indices.join(', '); } // Display results in the table function displayResults(data, jobInfoData) { // Clear previous results resultsTableBody.innerHTML = ''; // Populate table with data transformedData = data; data.forEach(row => { const tr = document.createElement('tr'); tr.innerHTML = `
${message}
`; errorContainer.classList.remove('hidden'); resultsContainer.classList.add('hidden'); jobInfo.classList.add('hidden'); // Scroll to error errorContainer.scrollIntoView({ behavior: 'smooth' }); } // Download CSV function downloadCSV() { if (transformedData.length === 0) return; // Create CSV content let csvContent = "CUSTPONBR,SKU,SHIPQTY,PACKAGEID\n"; transformedData.forEach(row => { csvContent += `${row.CUSTPONBR},${row.SKU},${row.SHIPQTY},${row.PACKAGEID}\n`; }); // Create download link const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' }); const url = URL.createObjectURL(blob); const link = document.createElement('a'); link.setAttribute('href', url); link.setAttribute('download', `transformed_data_${new Date().toISOString().slice(0, 10)}.csv`); link.style.visibility = 'hidden'; document.body.appendChild(link); link.click(); document.body.removeChild(link); }