`;
let currentHeader = '';
pathwayFields.forEach((field, index) => {
if (field.header !== currentHeader) {
currentHeader = field.header;
}
// Add flow arrow if not the first step
if (index > 0) {
html += `
`;
});
reviewArea.innerHTML = html;
pdfDownloadBtn.disabled = false;
switchTab(1); // Switch to review tab
}
/**
* PDF Generation Function
*/
function downloadPDF() {
const data = getFormData();
const { jsPDF } = window.jspdf;
const doc = new jsPDF('p', 'pt', 'a4');
let currentY = 40;
const margin = 40;
const pageWidth = doc.internal.pageSize.width;
const maxWidth = pageWidth - (margin * 2);
const checkPageBreak = (spaceNeeded) => {
if (currentY + spaceNeeded > doc.internal.pageSize.height - margin) {
doc.addPage();
currentY = margin;
}
};
const addText = (text, size = 11, style = 'normal', color = [0, 0, 0], indent = 0) => {
doc.setFontSize(size);
doc.setFont('Helvetica', style);
doc.setTextColor(color[0], color[1], color[2]);
const lines = doc.splitTextToSize(text, maxWidth - indent);
checkPageBreak(lines.length * (size * 1.2));
doc.text(lines, margin + indent, currentY);
currentY += (lines.length * (size * 1.2));
};
const addSectionBlock = (label, items, flowText, color) => {
checkPageBreak(50 + (items.length * 15));
// 1. Label Block
doc.setFillColor(color[0], color[1], color[2]);
doc.rect(margin, currentY, maxWidth, 20, 'F');
addText(label.toUpperCase(), 12, 'bold', [255, 255, 255]);
currentY -= 15; // Move cursor back up slightly for flow text
doc.setFontSize(10);
doc.setFont('Helvetica', 'normal');
doc.setTextColor(255, 255, 255);
doc.text(flowText, margin + 10, currentY);
currentY += 25; // Move below the colored bar
// 2. Content List
if (items.length === 0) {
doc.setFontSize(10);
doc.setFont('Helvetica', 'italic');
doc.setTextColor(150);
doc.text("N/A - No items defined.", margin + 10, currentY);
currentY += 15;
} else {
items.forEach(item => {
checkPageBreak(15);
doc.setFontSize(10);
doc.setFont('Helvetica', 'normal');
doc.setTextColor(0);
doc.text("•", margin + 5, currentY);
const lines = doc.splitTextToSize(item.trim(), maxWidth - 20);
doc.text(lines, margin + 15, currentY);
currentY += (lines.length * 12);
});
currentY += 10;
}
};
// --- PDF Content ---
// Title Block
doc.setFontSize(24);
doc.setFont('Helvetica', 'bold');
doc.setTextColor(39, 174, 96); /* Primary color */
doc.text("IMPACT PATHWAY DIAGRAM OUTLINE", pageWidth / 2, currentY, { align: 'center' });
currentY += 15;
doc.setFontSize(14);
doc.setFont('Helvetica', 'normal');
doc.setTextColor(44, 62, 80); /* Secondary color */
doc.text(`Project: ${data.title}`, pageWidth / 2, currentY, { align: 'center' });
currentY += 20;
doc.setFontSize(12);
doc.setFont('Helvetica', 'bold');
doc.text("Overall Goal (Impact Statement):", margin, currentY);
currentY += 15;
doc.setFontSize(12);
doc.setFont('Helvetica', 'italic');
const goalLines = doc.splitTextToSize(data.goal, maxWidth);
doc.text(goalLines, margin + 5, currentY);
currentY += (goalLines.length * 12) + 20;
doc.setTextColor(0);
// The Flowchart simulation
pathwayFields.forEach((field, index) => {
const items = data[field.id];
const colorMap = {
'Inputs': [52, 152, 219], // Blue
'Activities': [155, 89, 182], // Purple
'Outputs': [26, 188, 156], // Teal
'Short-Term Outcomes': [241, 196, 15], // Yellow
'Medium-Term Outcomes': [230, 126, 34], // Orange
'Long-Term Impact': [39, 174, 96] // Green
};
const color = colorMap[field.label] || [100, 100, 100];
// Add Section Block
addSectionBlock(field.label, items, field.flow, color);
// Add Down Arrow (except for the last one)
if (index < pathwayFields.length - 1) {
checkPageBreak(30);
doc.setFontSize(24);
doc.setFont('Helvetica', 'bold');
doc.setTextColor(46, 204, 113); // Success Color
doc.text("\u25BC", pageWidth / 2, currentY, { align: 'center' });
currentY += 20;
}
});
doc.save('impact_pathway_outline.pdf');
}
// --- Event Listeners ---
generateBtn.addEventListener('click', generatePathway);
pdfDownloadBtn.addEventListener('click', downloadPDF);
// --- Tab Navigation ---
function switchTab(tabIndex) {
tabs.forEach((tab, index) => {
tab.classList.toggle('active', index === tabIndex);
contents[index].classList.toggle('active', index === tabIndex);
});
currentTab = tabIndex;
updateNavButtons();
}
function updateNavButtons() {
prevBtn.disabled = currentTab === 0;
nextBtn.disabled = currentTab === tabs.length - 1;
}
tabs.forEach((tab, index) => {
tab.addEventListener('click', () => switchTab(index));
});
nextBtn.addEventListener('click', () => { if (currentTab < tabs.length - 1) switchTab(currentTab + 1); });
prevBtn.addEventListener('click', () => { if (currentTab > 0) switchTab(currentTab - 1); });
// --- Initial Setup ---
updateNavButtons();
});
▼
`; } html += `${field.label.toUpperCase()}
Flow: ${field.flow}
${formatList(data[field.id])}
