Last-Mile Delivery Cost Estimator

Last-Mile Delivery Cost Estimator

Estimate and compare last-mile delivery costs based on various factors.

${formatCurrency(r.totalCost)}

`; }).join(''); resultsContainer.innerHTML = `
${resultsHtml}
`; const ctx = document.getElementById('costChart').getContext('2d'); if (costChartInstance) costChartInstance.destroy(); costChartInstance = new Chart(ctx, { type: 'bar', data: { labels: results.map(r => r.method), datasets: [{ label: 'Total Estimated Cost', data: results.map(r => r.totalCost), backgroundColor: 'rgba(37, 99, 235, 0.6)' }] }, options: { responsive: true, maintainAspectRatio: false, scales: { y: { beginAtZero: true } }, plugins: { legend: { display: false } } } }); document.getElementById('download-pdf-btn').addEventListener('click', generatePdf); }; const renderConfiguration = () => { const configContent = document.getElementById('content-config'); if (!configContent) return; const methodsHtml = appData.methods.map((method, mIndex) => `

${method.name}

Location Multipliers

`).join(''); configContent.innerHTML = `
${methodsHtml}
`; document.getElementById('save-config-btn').addEventListener('click', handleConfigSave); }; const handleConfigSave = () => { document.querySelectorAll('#config-form input').forEach(input => { const mIndex = input.dataset.method; const fieldPath = input.dataset.field.split('.'); let target = appData.methods[mIndex]; for (let i = 0; i < fieldPath.length - 1; i++) { target = target[fieldPath[i]]; } target[fieldPath[fieldPath.length - 1]] = parseFloat(input.value); }); alert('Rate 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('Last-Mile Delivery Cost Report', pdf.internal.pageSize.getWidth() / 2, y, { align: 'center' }); y += 30; pdf.autoTable({ startY: y, theme: 'plain', body: [ ['Distance:', `${calculationInputs.distance} miles`, 'Speed:', calculationInputs.deliverySpeed], ['Zone:', calculationInputs.locationType, 'Size:', calculationInputs.packageSize], ] }); y = pdf.autoTable.previous.finalY + 30; pdf.autoTable({ startY: y, head: [['Delivery Method', 'Est. Time', 'Total Cost']], body: calculationResult.results.map(r => [r.method, r.deliveryTime, formatCurrency(r.totalCost)]), theme: 'grid', headStyles: { fillColor: [37, 99, 235] } // Blue header }); pdf.save(`Last-Mile-Cost-Report.pdf`); loadingOverlay.style.display = 'none'; }; 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: 'Cost Estimator', id: 'estimator' }, { 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)); }); renderEstimator(); 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