Multi-Carrier Shipping Cost Calculator

Multi-Carrier Shipping Cost Calculator

Compare shipping rates between major carriers instantly.

Enter shipment details to compare costs.

`; document.getElementById('calculator-form').addEventListener('submit', handleCalculation); }; const handleCalculation = (e) => { e.preventDefault(); // Gather inputs const originZip = parseInt(document.getElementById('origin-zip').value); const destZip = parseInt(document.getElementById('dest-zip').value); const weight = parseFloat(document.getElementById('weight').value); const length = parseFloat(document.getElementById('length').value); const width = parseFloat(document.getElementById('width').value); const height = parseFloat(document.getElementById('height').value); if (isNaN(originZip) || isNaN(destZip) || isNaN(weight) || isNaN(length) || isNaN(width) || isNaN(height)) { alert('Please fill all fields with valid numbers.'); return; } calculationInputs = { originZip, destZip, weight, length, width, height }; const dimWeight = (length * width * height) / 139; // Standard dimensional weight factor const billableWeight = Math.max(weight, dimWeight); const distance = Math.abs(originZip - destZip); let results = []; appData.carriers.forEach(carrier => { carrier.services.forEach(service => { let cost = service.baseRate + (billableWeight * service.perPound) + (distance * service.distanceFactor); if (appData.handlingFee.type === 'fixed') { cost += appData.handlingFee.value; } else if (appData.handlingFee.type === 'percent') { cost *= (1 + appData.handlingFee.value / 100); } results.push({ carrier: carrier.name, service: service.name, cost: cost, deliveryTime: service.time[0] === service.time[1] ? `${service.time[0]} days` : `${service.time[0]}-${service.time[1]} days`, deliverySortKey: service.time[0] }); }); }); const cheapest = results.reduce((prev, curr) => prev.cost < curr.cost ? prev : curr); const fastest = results.reduce((prev, curr) => prev.deliverySortKey < curr.deliverySortKey ? prev : curr); calculationResult = { results, cheapest, fastest }; renderResults(); }; const renderResults = () => { const resultsContainer = document.getElementById('results-container'); if (!calculationResult) return; const { results, cheapest, fastest } = calculationResult; const resultsHtml = results.map(r => { const isCheapest = r.carrier === cheapest.carrier && r.service === cheapest.service; const isFastest = r.carrier === fastest.carrier && r.service === fastest.service; let classes = 'result-card bg-white p-4 rounded-lg shadow-sm'; let tags = ''; if (isCheapest) { classes += ' cheapest'; tags += `Cheapest`; } if (isFastest) { classes += ' fastest'; tags += `Fastest`; } return `

${r.carrier} ${r.service}

Est. ${r.deliveryTime}

${formatCurrency(r.cost)}

${tags}
`; }).join(''); resultsContainer.innerHTML = `

Available Rates

${resultsHtml}
`; lucide.createIcons(); document.getElementById('download-pdf-btn').addEventListener('click', generatePdf); }; const renderConfiguration = () => { const configContent = document.getElementById('content-config'); if (!configContent) return; const carriersHtml = appData.carriers.map((carrier, cIndex) => `

${carrier.name}

${carrier.services.map((service, sIndex) => `
${service.name}
`).join('')}
`).join(''); configContent.innerHTML = `

Carrier Rate Configuration

${carriersHtml}

Handling Fee

`; document.getElementById('save-config-btn').addEventListener('click', handleConfigSave); }; const handleConfigSave = (e) => { e.preventDefault(); document.querySelectorAll('#config-form input').forEach(input => { const cIndex = input.dataset.carrier; const sIndex = input.dataset.service; const field = input.dataset.field; appData.carriers[cIndex].services[sIndex][field] = parseFloat(input.value); }); appData.handlingFee.type = document.getElementById('handling-fee-type').value; appData.handlingFee.value = parseFloat(document.getElementById('handling-fee-value').value); alert('Configuration saved!'); }; const generatePdf = () => { if (!calculationResult) return; loadingOverlay.style.display = 'flex'; const { jsPDF } = window.jspdf; const pdf = new jsPDF({ orientation: 'p', unit: 'pt', format: 'a4' }); let y = 40; pdf.setFontSize(18).setFont('helvetica', 'bold').text('Shipping Cost Analysis Report', pdf.internal.pageSize.getWidth() / 2, y, { align: 'center' }); y += 30; pdf.setFontSize(12).setFont('helvetica', 'bold').text('Shipment Details', 40, y); y += 15; pdf.autoTable({ startY: y, theme: 'plain', body: [ ['Origin ZIP:', calculationInputs.originZip, 'Weight:', `${calculationInputs.weight} lbs`], ['Destination ZIP:', calculationInputs.destZip, 'Dimensions:', `${calculationInputs.length}x${calculationInputs.width}x${calculationInputs.height} in`], ] }); y = pdf.autoTable.previous.finalY + 30; pdf.autoTable({ startY: y, head: [['Carrier', 'Service', 'Est. Delivery', 'Cost']], body: calculationResult.results.map(r => [r.carrier, r.service, r.deliveryTime, formatCurrency(r.cost)]), theme: 'grid', headStyles: { fillColor: [13, 148, 136] } // Teal header }); pdf.save(`Shipping-Cost-Report.pdf`); loadingOverlay.style.display = 'none'; }; // --- TAB NAVIGATION & INITIALIZATION --- const switchTab = (tabIndex) => { activeTabIndex = tabIndex; document.querySelectorAll('.tab-btn').forEach((btn, i) => btn.classList.toggle('active', i === tabIndex)); document.querySelectorAll('.tab-content').forEach((content, i) => content.classList.toggle('hidden', i !== tabIndex)); updateNavButtons(); }; const updateNavButtons = () => { prevTabBtn.disabled = activeTabIndex === 0; nextTabBtn.disabled = activeTabIndex === tabIdentifiers.length - 1; }; const initializeUI = () => { const tabs = [ { name: 'Rate Calculator', id: 'calculator' }, { name: 'Rate Configuration', id: 'config' } ]; tabIdentifiers = tabs.map(t => t.id); tabsContainer.innerHTML = tabs.map(tab => ``).join(''); mainContent.innerHTML = tabs.map(tab => `
`).join(''); tabs.forEach((tab, index) => { document.getElementById(`tab-${tab.id}`).addEventListener('click', () => switchTab(index)); }); renderCalculator(); renderConfiguration(); switchTab(0); lucide.createIcons(); }; initializeUI(); prevTabBtn.addEventListener('click', () => { if (activeTabIndex > 0) switchTab(activeTabIndex - 1); }); nextTabBtn.addEventListener('click', () => { if (activeTabIndex < tabIdentifiers.length - 1) switchTab(activeTabIndex + 1); }); });
Scroll to Top