Land Parcel Price Comparison Tool

Land Parcel Price Comparison Tool

Analyze and compare multiple land parcels to find the best value.

Add a Land Parcel

$

Comparison Dashboard

No parcels added

Add a land parcel in the Data Configuration tab to start comparing.

${item.name}

${isBestValue ? 'Best Value' : ''} ${item.size} ${formatCurrency(item.price)} ${formatCurrency(item.pricePerAcre)} `; comparisonTableBody.appendChild(row); }); } function addParcel() { const nameInput = document.getElementById('parcelName'); const sizeInput = document.getElementById('parcelSize'); const priceInput = document.getElementById('parcelPrice'); const name = nameInput.value.trim(); const size = parseFloat(sizeInput.value); const price = parseFloat(priceInput.value); if (!name || isNaN(size) || isNaN(price) || size <= 0 || price <= 0) { showCustomMessage('Invalid Input', 'Please fill all fields with valid data.', 'error'); return; } comparisonList.push({ id: Date.now(), name, size, price, pricePerAcre: price / size }); nameInput.value = ''; sizeInput.value = ''; priceInput.value = ''; nameInput.focus(); showCustomMessage('Success', `Parcel "${name}" added to comparison.`, 'success'); renderTable(); } function updateTabView() { Object.values(tabButtons).forEach(b => b.classList.remove('active')); Object.values(tabContents).forEach(c => c.classList.remove('active')); tabButtons[currentTab].classList.add('active'); tabContents[currentTab].classList.add('active'); prevBtn.style.visibility = currentTab === 1 ? 'hidden' : 'visible'; nextBtn.textContent = currentTab === 1 ? 'Compare' : 'Next'; nextBtn.style.visibility = currentTab === 2 ? 'hidden' : 'visible'; } function goToTab(tabNumber) { if (tabNumber > currentTab && currentTab === 1) { renderTable(); } currentTab = tabNumber; updateTabView(); } function downloadPdf() { if(comparisonList.length === 0) { showCustomMessage('No Data', 'Please add parcels to generate a PDF.', 'warning'); return; } const { jsPDF } = window.jspdf; const doc = new jsPDF(); doc.setFontSize(22); doc.setFont('helvetica', 'bold'); doc.text("Land Parcel Comparison Report", 105, 20, { align: 'center' }); const tableData = [...comparisonList] .sort((a, b) => a.pricePerAcre - b.pricePerAcre) .map(item => [item.name, item.size, formatCurrency(item.price), formatCurrency(item.pricePerAcre)]); doc.autoTable({ startY: 30, head: [['Parcel Name', 'Size (Acres)', 'Total Price', 'Price per Acre']], body: tableData, theme: 'striped', headStyles: { fillColor: [37, 99, 235] }, didDrawCell: (data) => { if (data.section === 'body' && data.row.index === 0) { doc.setFont('helvetica', 'bold'); } } }); doc.save('Land_Parcel_Comparison.pdf'); } function showCustomMessage(title, body, type) { const box = document.getElementById('message-box'), titleEl = document.getElementById('message-title'), bodyEl = document.getElementById('message-body'), iconContainer = document.getElementById('message-icon-container'); if(!box || !titleEl || !bodyEl || !iconContainer) return; titleEl.textContent = title; bodyEl.textContent = body; let iconSvg = ''; switch (type) { case 'success': iconSvg = ``; break; case 'error': iconSvg = ``; break; case 'warning': iconSvg = ``; break; } iconContainer.innerHTML = iconSvg; box.classList.add('show'); setTimeout(() => { box.classList.remove('show'); }, 4000); } prevBtn.addEventListener('click', () => goToTab(Math.max(1, currentTab - 1))); nextBtn.addEventListener('click', () => goToTab(Math.min(2, currentTab + 1))); addParcelBtn.addEventListener('click', addParcel); pdfDownloadBtn.addEventListener('click', downloadPdf); clearBtn.addEventListener('click', () => { comparisonList = []; renderTable(); showCustomMessage('Cleared', 'All parcels have been removed from the comparison.', 'success'); }); comparisonTableBody.addEventListener('click', (e) => { const removeBtn = e.target.closest('.remove-btn'); if (removeBtn) { const idToRemove = parseInt(removeBtn.dataset.id, 10); comparisonList = comparisonList.filter(item => item.id !== idToRemove); renderTable(); } }); updateTabView(); renderTable(); });
Scroll to Top