Please select an item category in the first tab.
";
return;
}
const factors = ADJUSTMENT_FACTORS_DB[currentEstimation.itemCategory] || ADJUSTMENT_FACTORS_DB["OtherCollectible"];
if (!factors) {
factorAdjustmentsContainer.innerHTML = "
No specific adjustment factors defined for this category. Generic factors will be used if available, or proceed to summary.
";
return;
}
currentEstimation.factorAdjustments = []; // Reset previous adjustments for this category
let tableHTML = `
Factor Your Item vs. Comparable (Select how your item compares) Illustrative Adjustment
`;
factors.forEach((factor, index) => {
// Initialize with default choice and adjustment
const defaultChoice = factor.default || Object.keys(factor.choices)[0]; // Fallback to first choice if no default
const defaultAdjustment = factor.choices[defaultChoice];
currentEstimation.factorAdjustments.push({
factorName: factor.name,
userChoice: defaultChoice, // Store the text of the choice
percentAdjustment: defaultAdjustment
});
tableHTML += `
${factor.name} ${factor.note || ''}
`;
for (const choice in factor.choices) {
tableHTML += `${choice} `;
}
tableHTML += `
${(defaultAdjustment * 100).toFixed(0)}%
`;
});
tableHTML += `
`;
factorAdjustmentsContainer.innerHTML = tableHTML;
// Add event listeners to new select elements
factorAdjustmentsContainer.querySelectorAll('.acpe-factor-choice').forEach(selectElement => {
selectElement.addEventListener('change', handleFactorChange);
});
}
function handleFactorChange(event) {
const selectElement = event.target;
const factorIndex = parseInt(selectElement.getAttribute('data-factor-index'));
const selectedOptionText = selectElement.options[selectElement.selectedIndex].text;
const percentAdjustment = parseFloat(selectElement.value);
if (currentEstimation.factorAdjustments[factorIndex]) {
currentEstimation.factorAdjustments[factorIndex].userChoice = selectedOptionText;
currentEstimation.factorAdjustments[factorIndex].percentAdjustment = percentAdjustment;
const displayCell = document.getElementById(`acpe_adj_display_${factorIndex}`);
if(displayCell) displayCell.textContent = `${(percentAdjustment * 100).toFixed(0)}%`;
}
}
// --- Summary Tab Logic ---
function calculateAndDisplaySummary() {
if (!currentEstimation.itemCategory || currentEstimation.comparable.price === null) {
resultsSummaryContainer.style.display = 'none';
noEstimationYetMsg.style.display = 'block';
pdfDownloadButtonContainer.style.display = 'none';
return;
}
summaryItemCategory.textContent = currentEstimation.itemCategory.replace(/_/g, ' ');
summaryItemDescription.textContent = currentEstimation.itemDescription;
let displayCurrency = currentEstimation.comparable.currency === 'Other' ?
(currentEstimation.comparable.otherSymbol || 'N/A') :
getCurrencySymbol(currentEstimation.comparable.currency);
summaryBaseComparablePrice.textContent = `${formatNumber(currentEstimation.comparable.price)} ${displayCurrency}`;
summaryComparableCurrency.textContent = displayCurrency;
summaryAdjustmentsList.innerHTML = '';
let netAdjustment = 0;
currentEstimation.factorAdjustments.forEach(adj => {
netAdjustment += adj.percentAdjustment;
const listItem = document.createElement('li');
const adjPercentText = (adj.percentAdjustment * 100).toFixed(0) + '%';
listItem.innerHTML = `
${adj.factorName} (Choice: ${adj.userChoice}):
${adjPercentText} `;
summaryAdjustmentsList.appendChild(listItem);
});
currentEstimation.netAdjustment = netAdjustment;
summaryNetAdjustmentPercent.textContent = `${(netAdjustment * 100).toFixed(0)}%`;
summaryNetAdjustmentPercent.className = netAdjustment >= 0 ? 'adjustment-positive' : 'adjustment-negative';
const adjustedPrice = currentEstimation.comparable.price * (1 + netAdjustment);
// Provide a conceptual range, e.g., +/- 15% of the adjusted price
const rangeFactor = 0.15;
currentEstimation.estimatedLow = adjustedPrice * (1 - rangeFactor);
currentEstimation.estimatedHigh = adjustedPrice * (1 + rangeFactor);
summaryEstimatedValueRange.textContent = `${formatNumber(currentEstimation.estimatedLow)} - ${formatNumber(currentEstimation.estimatedHigh)} ${displayCurrency}`;
resultsSummaryContainer.style.display = 'block';
noEstimationYetMsg.style.display = 'none';
pdfDownloadButtonContainer.style.display = 'block';
}
function formatNumber(num, digits = 0) {
if (num === null || num === undefined || isNaN(num)) return 'N/A';
return num.toLocaleString(undefined, {minimumFractionDigits: digits, maximumFractionDigits: digits});
}
function getCurrencySymbol(currencyCode) {
const symbols = { USD: '$', EUR: '€', GBP: '£', JPY: '¥', CAD: 'C$', AUD: 'A$', CHF: 'CHF' };
return symbols[currencyCode] || currencyCode; // Fallback to code itself
}
// --- PDF Generation ---
const downloadPdfButton = document.getElementById('acpeDownloadPdfButton');
if (downloadPdfButton) {
downloadPdfButton.addEventListener('click', generatePdfReport);
}
function generatePdfReport() {
if (typeof window.jspdf === 'undefined' || typeof window.jspdf.jsPDF === 'undefined') {
alert('PDF library (jsPDF) not loaded. Cannot generate PDF.'); return;
}
if (!currentEstimation.itemCategory || currentEstimation.comparable.price === null) {
alert("Please complete all estimation steps before generating a PDF."); return;
}
const { jsPDF } = window.jspdf;
const doc = new jsPDF();
let yPos = 20;
const leftMargin = 15;
const contentWidth = doc.internal.pageSize.getWidth() - (2 * leftMargin);
const checkPdfPageBreak = (neededHeight = 20) => {
if (yPos + neededHeight > doc.internal.pageSize.getHeight() - 20) {
doc.addPage(); yPos = 20;
}
};
doc.setFontSize(18);
doc.text("Art & Collectibles Conceptual Estimation Report", doc.internal.pageSize.getWidth() / 2, yPos, { align: 'center' });
yPos += 10;
doc.setFontSize(10);
doc.text(`Report Generated: ${new Date().toLocaleDateString()}`, leftMargin, yPos);
yPos += 10;
doc.setLineWidth(0.5);
doc.line(leftMargin, yPos, leftMargin + contentWidth, yPos);
yPos += 10;
doc.setFontSize(12); doc.setFont(undefined, 'bold');
doc.text("Your Item:", leftMargin, yPos); yPos += 6;
doc.setFontSize(10); doc.setFont(undefined, 'normal');
doc.text(`Category: ${currentEstimation.itemCategory.replace(/_/g, ' ')}`, leftMargin + 5, yPos); yPos += 5;
let wrappedDesc = doc.splitTextToSize(`Description: ${currentEstimation.itemDescription}`, contentWidth - 5);
doc.text(wrappedDesc, leftMargin + 5, yPos); yPos += (wrappedDesc.length * 4) + 2;
if(currentEstimation.itemNotes) {
let wrappedNotes = doc.splitTextToSize(`Additional Notes: ${currentEstimation.itemNotes}`, contentWidth - 5);
doc.text(wrappedNotes, leftMargin + 5, yPos); yPos += (wrappedNotes.length * 4) + 2;
}
yPos += 5;
checkPdfPageBreak();
doc.setFontSize(12); doc.setFont(undefined, 'bold');
doc.text("Base Comparable Item:", leftMargin, yPos); yPos += 6;
doc.setFontSize(10); doc.setFont(undefined, 'normal');
let compCurrency = currentEstimation.comparable.currency === 'Other' ?
(currentEstimation.comparable.otherSymbol || 'N/A') :
currentEstimation.comparable.currency;
doc.text(`Description: ${currentEstimation.comparable.description}`, leftMargin + 5, yPos); yPos += 5;
doc.text(`Price: ${formatNumber(currentEstimation.comparable.price)} ${compCurrency}`, leftMargin + 5, yPos); yPos += 5;
doc.text(`Sale/Listing Date: ${currentEstimation.comparable.date}`, leftMargin + 5, yPos); yPos += 5;
doc.text(`Source: ${currentEstimation.comparable.source}`, leftMargin + 5, yPos); yPos += 10;
checkPdfPageBreak(currentEstimation.factorAdjustments.length * 7 + 20); // Estimate height for table
doc.setFontSize(12); doc.setFont(undefined, 'bold');
doc.text("Factor Adjustments Applied:", leftMargin, yPos); yPos += 7;
const head = [['Factor', 'User Assessment', 'Illustrative Adjustment']];
const body = currentEstimation.factorAdjustments.map(adj => [
adj.factorName,
adj.userChoice,
`${(adj.percentAdjustment * 100).toFixed(0)}%`
]);
doc.autoTable({
startY: yPos,
head: head,
body: body,
theme: 'grid',
headStyles: { fillColor: [52, 86, 139] }, // primary-color
styles: { fontSize: 9, cellPadding: 2 },
margin: {left: leftMargin, right: leftMargin},
didDrawPage: function(data) { yPos = data.cursor.y + 5; }
});
yPos = doc.autoTable.previous.finalY + 10;
checkPdfPageBreak();
doc.setFontSize(11); doc.setFont(undefined, 'bold');
doc.text(`Net Illustrative Adjustment Percentage: ${(currentEstimation.netAdjustment * 100).toFixed(0)}%`, leftMargin, yPos); yPos += 10;
doc.setFontSize(12); doc.setFont(undefined, 'bold');
doc.setFillColor(230, 240, 255); // Light blue background for final estimate
doc.rect(leftMargin - 2, yPos - 7, contentWidth + 4, 18, 'F');
doc.setTextColor(52, 86, 139); // primary-color
doc.text("Conceptual Adjusted Estimated Value Range:", leftMargin, yPos); yPos += 7;
doc.setFontSize(14);
doc.text(`${formatNumber(currentEstimation.estimatedLow)} - ${formatNumber(currentEstimation.estimatedHigh)} ${compCurrency}`, leftMargin, yPos);
yPos += 15;
doc.setTextColor(0,0,0); // Reset color
checkPdfPageBreak();
doc.setFontSize(8); doc.setFont(undefined, 'italic');
doc.text("Disclaimer: This report is a conceptual estimation based on user-provided data and predefined illustrative adjustments. It is not a professional appraisal and should not be used for financial, legal, or insurance purposes. Consult a qualified appraiser for formal valuations.", leftMargin, yPos, {maxWidth: contentWidth});
doc.save("Art_Collectible_Estimation_Report.pdf");
}
// --- Initial Load ---
if (itemCategorySelect) { // Ensure element exists before adding listener
itemCategorySelect.addEventListener('change', renderFactorAdjustmentsTable);
} else {
console.error("Item category select element not found.");
}
// Initial call to setup tabs and default states
if (TABS_ELEMENTS.length > 0) {
switchTab(0);
} else {
console.error("Tab button elements not found for initialization.");
}
});