${rpc_escapeHTML(item.status)}
`;
}).join('');
sectionDiv.innerHTML = `
${rpc_escapeHTML(category)}
${itemsHTML}
`;
rpc_dashboardOutput.appendChild(sectionDiv);
});
rpc_updateProgress(completedCount, rpc_data.items.length);
rpc_addDashboardListeners();
}
/**
* Updates the completion summary and progress bar
*/
function rpc_updateProgress(completed, total) {
rpc_completedCount.textContent = completed;
rpc_totalCount.textContent = total;
const percentage = total > 0 ? (completed / total) * 100 : 0;
rpc_progressFill.style.width = `${percentage}%`;
}
/**
* Updates the status for a specific item in the rpc_data object
*/
function rpc_updateItemStatus(id, newStatus) {
const itemIndex = rpc_data.items.findIndex(item => item.id === id);
if (itemIndex !== -1) {
rpc_data.items[itemIndex].status = newStatus;
rpc_renderDashboard(); // Re-render to update badges and progress
}
}
function rpc_addDashboardListeners() {
rpc_dashboardOutput.querySelectorAll('.rpc-dashboard-status').forEach(select => {
select.addEventListener('change', (e) => {
const id = parseInt(e.target.closest('.w-48').getAttribute('data-id'), 10);
const newStatus = e.target.value;
rpc_updateItemStatus(id, newStatus);
});
});
}
/**
* Renders a clone for PDF generation
*/
function rpc_renderPdfClone() {
rpc_pdfRenderClone.innerHTML = `
Retirement Planning Checklist
Overall Progress:
${rpc_completedCount.textContent} /
${rpc_totalCount.textContent} Items Completed
`;
// Render data into the clone's content area
const contentArea = rpc_pdfRenderClone.querySelector('.space-y-6');
rpc_renderDashboard(contentArea); // Render full list to the clone
}
/**
* Generates and downloads a PDF of the checklist
*/
async function rpc_downloadPDF() {
if (rpc_data.items.length === 0) {
alert("The checklist is empty. Please add tasks before downloading.");
return;
}
if (typeof jspdf === 'undefined' || typeof html2canvas === 'undefined') {
alert("Error: PDF libraries failed to load.");
return;
}
rpc_renderPdfClone();
const { jsPDF } = window.jspdf;
try {
const canvas = await html2canvas(rpc_pdfRenderClone, { scale: 1.5, useCORS: true });
const imgData = canvas.toDataURL('image/png');
const imgProps = { width: canvas.width, height: canvas.height };
const pdf = new jsPDF({ orientation: 'p', unit: 'pt', format: 'a4' });
const pdfWidth = pdf.internal.pageSize.getWidth();
const pdfHeight = pdf.internal.pageSize.getHeight();
const margin = 40;
const contentWidth = pdfWidth - (margin * 2);
const contentHeight = (contentWidth * imgProps.height) / imgProps.width;
let heightLeft = contentHeight;
let position = 0;
pdf.addImage(imgData, 'PNG', margin, position + margin, contentWidth, contentHeight);
heightLeft -= (pdfHeight - margin * 2);
while (heightLeft > 0) {
position -= (pdfHeight - margin * 2);
pdf.addPage();
pdf.addImage(imgData, 'PNG', margin, position + margin, contentWidth, contentHeight);
heightLeft -= (pdfHeight - margin * 2);
}
pdf.save('Retirement_Checklist.pdf');
} catch (error) {
console.error("PDF generation failed:", error);
alert("An error occurred while generating the PDF.");
}
}
// --- EVENT LISTENERS ---
// Tab link clicks
rpc_tabLinks.forEach((link, index) => {
link.addEventListener('click', () => rpc_switchTab(index));
});
// Next/Prev button clicks
if (rpc_prevButton) {
rpc_prevButton.addEventListener('click', () => {
if (rpc_currentTab > 0) rpc_switchTab(rpc_currentTab - 1);
});
}
if (rpc_nextButton) {
rpc_nextButton.addEventListener('click', () => {
if (rpc_currentTab === rpc_tabLinks.length - 1) {
rpc_updateDataFromConfig();
rpc_switchTab(0);
} else {
if (rpc_currentTab < rpc_tabLinks.length - 1) rpc_switchTab(rpc_currentTab + 1);
}
});
}
// PDF download
if (rpc_downloadPdfButton) {
rpc_downloadPdfButton.addEventListener('click', rpc_downloadPDF);
}
// --- Config Tab Listeners ---
if (rpc_addItemButton) {
rpc_addItemButton.addEventListener('click', () => {
rpc_itemsContainer.appendChild(rpc_createItemInput());
});
}
if (rpc_configTab) {
// Handle remove
rpc_configTab.addEventListener('click', (e) => {
const removeButton = e.target.closest('.rpc-remove-item');
if (removeButton) {
removeButton.closest('.border[data-id]').remove();
if(rpc_itemsContainer.children.length === 0){
rpc_itemsContainer.appendChild(rpc_createItemInput());
}
}
});
}
// --- INITIALIZATION ---
rpc_initSampleData();
rpc_renderConfig();
rpc_renderDashboard();
// Set initial tab state
rpc_tabPanes.forEach((pane, index) => {
pane.classList.toggle('hidden', index !== 0);
pane.classList.toggle('rpc-active', index === 0);
});
rpc_tabLinks.forEach((link, index) => {
TAB_CLASSES.active.forEach(cls => link.classList.remove(cls));
TAB_CLASSES.inactive.forEach(cls => link.classList.remove(cls));
if (index === 0) {
TAB_CLASSES.active.forEach(cls => link.classList.add(cls));
} else {
TAB_CLASSES.inactive.forEach(cls => link.classList.add(cls));
}
});
});