Please select at least one prompt in the Builder tab.
';
pdfDownloadBtn.disabled = true;
return;
}
// --- 1. Header ---
let html = `
${data.title}
Type: ${data.type} Circle | Participants: ${data.participants}
Follow the prompts below using the talking piece. Ensure all participants have a chance to speak without interruption.
`;
// --- 2. Phases ---
data.phases.forEach((phase, index) => {
html += `
Phase ${index + 1}: ${phase.name}
Purpose: ${phase.context}
- Facilitator speaks first: "Welcome everyone. The purpose of this circle is to [State purpose using Title/Type]."
- Facilitator introduces the talking piece and ground rules.
- Core Prompt: ${phase.prompt}
`;
});
reviewArea.innerHTML = html;
pdfDownloadBtn.disabled = false;
switchTab(1); // Switch to review tab
}
/**
* PDF Generation Function
* V.A.1, IX: MUST be fully functional and nicely formatted.
*/
function downloadPDF() {
const data = getScriptData();
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;
}
};
// Helper to add text and manage Y position
const addText = (text, size = 11, style = 'normal', indent = 0, color = 0) => {
doc.setFontSize(size);
doc.setFont('Helvetica', style);
doc.setTextColor(color);
const lines = doc.splitTextToSize(text, maxWidth - indent);
checkPageBreak(lines.length * (size * 0.8));
doc.text(lines, margin + indent, currentY);
currentY += (lines.length * (size * 1.2)); // Line height multiplier
doc.setTextColor(0); // Reset color
};
// --- PDF Content ---
// Title Block
doc.setFontSize(22);
doc.setFont('Helvetica', 'bold');
doc.setTextColor(0, 123, 255); // Primary color
addText(data.title.toUpperCase(), 22, 'bold', 0, [0, 123, 255]);
doc.setFontSize(14);
addText(`Type: ${data.type} Circle | Participants: ${data.participants}`, 14, 'normal', 0, [108, 117, 125]);
currentY += 15;
// Introduction
addText('Restorative Circle Facilitation Script', 12, 'bold');
addText('Follow the prompts below using the talking piece. Ensure all participants have a chance to speak without interruption.', 10, 'italic', 5);
currentY += 10;
// Phases
data.phases.forEach((phase, index) => {
checkPageBreak(50); // Ensure enough space for the whole phase block
// Phase Header
doc.setDrawColor(0, 123, 255); // Primary color border
doc.setLineWidth(2);
doc.line(margin, currentY, margin, currentY + 30);
doc.setFontSize(15);
doc.setFont('Helvetica', 'bold');
doc.setTextColor(0, 123, 255); // Primary color
addText(`Phase ${index + 1}: ${phase.name}`, 15, 'bold', 10, [0, 123, 255]);
// Purpose/Context
addText(`Purpose: ${phase.context}`, 10, 'italic', 10, [108, 117, 125]);
// Step 1
addText(`1. Facilitator speaks first: "Welcome everyone. The purpose of this circle is to [State purpose using Title/Type]."`, 10, 'normal', 10);
// Step 2
addText('2. Facilitator introduces the talking piece and ground rules.', 10, 'normal', 10);
// Core Prompt (Highlighted)
doc.setFontSize(12);
doc.setFont('Helvetica', 'bold');
doc.setTextColor(40, 167, 69); // Success color
addText(`3. Core Prompt: ${phase.prompt}`, 12, 'bold', 10, [40, 167, 69]);
currentY += 10;
});
doc.save(`${data.title.replace(/\s/g, '_') || 'Restorative_Circle'}_Script.pdf`);
}
// --- Event Listeners ---
generateBtn.addEventListener('click', generateScript);
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 ---
populatePhaseSelects();
renderPromptLibrary();
updateNavButtons();
});