Add experiences in Section 3 to link them here.
'; return; } const narrativeId = checklist.id.replace('-checklist', ''); experiences.forEach(exp => { const item = document.createElement('div'); item.className = 'plar-checkbox-item'; item.innerHTML = ` `; checklist.appendChild(item); }); }); } // --- Review & PDF Functions --- function getFullPortfolioData() { const data = {}; // 1. Personal Info data.principal = { name: document.getElementById('plar-name').value, email: document.getElementById('plar-email').value, phone: document.getElementById('plar-phone').value, }; // 2. Target Course const course = courses.find(c => c.id === targetCourseSelect.value); data.course = course || { name: 'N/A', code: 'N/A' }; // 3. Experiences data.experiences = [...experiences]; // 4. Narratives (Read from dynamic form) data.narratives = []; const narrativeFieldsets = narrativesSection.querySelectorAll('fieldset'); narrativeFieldsets.forEach(fieldset => { const id = fieldset.id; const objective = narrativesData[id].objective; const narrativeText = fieldset.querySelector(`#${id}-text`).value; const documents = fieldset.querySelector(`#${id}-docs`).value; const linkedExp = []; fieldset.querySelectorAll(`#${id}-checklist input[type="checkbox"]:checked`).forEach(checkbox => { const exp = experiences.find(e => e.id === checkbox.dataset.expId); if (exp) linkedExp.push(exp.title); }); data.narratives.push({ objective, narrativeText, documents, linkedExp }); }); return data; } function renderReviewSheet() { const data = getFullPortfolioData(); let experiencesHTML = 'No experiences added.
'; if (data.experiences.length > 0) { experiencesHTML = data.experiences.map(exp => `
${exp.title} (${exp.org}, ${exp.dates})
`).join('');
}
let narrativesHTML = '${exp.desc}
No objectives found for this course.
'; if (data.narratives.length > 0) { narrativesHTML = data.narratives.map(n => `Objective: ${n.objective}
${n.narrativeText || 'No narrative written.'}
Supported By: ${n.linkedExp.join(', ') || 'None linked'}
Documents: ${n.documents || 'None listed'}
PLAR Portfolio Prep Sheet
Student Information
Name: ${data.principal.name}
Email: ${data.principal.email}
Phone: ${data.principal.phone}
Target Course
Course: ${data.course.name} (${data.course.code})
Summary of Experience
${experiencesHTML}Learning Narratives & Evidence
${narrativesHTML}This is a preparation sheet, NOT a formal portfolio.
`; } function downloadPDF() { const { jsPDF } = window.jspdf; const doc = new jsPDF(); const data = getFullPortfolioData(); const pageHeight = doc.internal.pageSize.height; const pageWidth = doc.internal.pageSize.width; const margin = 20; const maxWidth = pageWidth - (margin * 2); let currentY = margin; const checkPageBreak = (spaceNeeded) => { if (currentY + spaceNeeded > pageHeight - margin) { doc.addPage(); currentY = margin; } }; const addSection = (title) => { checkPageBreak(20); doc.setFontSize(16); doc.setFont(undefined, 'bold'); doc.text(title, margin, currentY); currentY += 7; doc.setLineWidth(0.5); doc.line(margin, currentY, maxWidth + margin, currentY); currentY += 10; }; const addText = (text, size = 11, style = 'normal', indent = 0) => { checkPageBreak(10); doc.setFontSize(size); doc.setFont(undefined, style); const lines = doc.splitTextToSize(text, maxWidth - indent); doc.text(lines, margin + indent, currentY); currentY += (lines.length * (size * 0.4)) + 5; }; // --- PDF Content --- doc.setFontSize(20); doc.setFont(undefined, 'bold'); doc.text("PLAR Portfolio Prep Sheet", pageWidth / 2, currentY, { align: 'center' }); currentY += 15; // Student Info addSection("Student Information"); addText(`Name: ${data.principal.name}`); addText(`Email: ${data.principal.email}`); addText(`Phone: ${data.principal.phone}`); // Target Course addSection("Target Course"); addText(`${data.course.name} (${data.course.code})`); // Experience addSection("Summary of Experience"); if (data.experiences.length > 0) { data.experiences.forEach(exp => { checkPageBreak(20); addText(`${exp.title}`, 12, 'bold'); addText(`${exp.org} (${exp.dates})`, 11, 'italic', 5); addText(exp.desc, 11, 'normal', 5); currentY += 5; }); } else { addText("No experiences added.", 11, 'italic'); } // Narratives addSection("Learning Narratives & Evidence"); if (data.narratives.length > 0) { data.narratives.forEach(n => { checkPageBreak(40); addText(`Objective: ${n.objective}`, 12, 'bold'); addText(n.narrativeText || 'No narrative written.', 11, 'italic', 5); addText(`Linked Experience: ${n.linkedExp.join(', ') || 'None'}`, 10, 'normal', 5); addText(`Supporting Documents: ${n.documents || 'None'}`, 10, 'normal', 5); currentY += 10; }); } else { addText("No objectives or narratives found.", 11, 'italic'); } // Footer checkPageBreak(20); currentY = pageHeight - margin - 10; doc.setFontSize(10); doc.setFont(undefined, 'bold'); doc.text("This is a preparation sheet, NOT a formal portfolio.", pageWidth / 2, currentY, { align: 'center' }); doc.save('plar-prep-sheet.pdf'); } // --- 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; // Re-order tabs to match spec (Dashboard first, Config last) const dashboardTab = tabs[0]; const reviewTab = tabs[1]; const configTab = tabs[2]; const tabContainer = document.querySelector('.plar-tabs'); tabContainer.innerHTML = ''; tabContainer.appendChild(dashboardTab); tabContainer.appendChild(reviewTab); tabContainer.appendChild(configTab); } tabs.forEach((tab, index) => { tab.addEventListener('click', () => { // Find the *actual* index from the DOM order, not the initial 'index' const tabNode = tab.closest('.plar-tab-button'); const newIndex = Array.from(tabNode.parentNode.children).indexOf(tabNode); switchTab(newIndex); }); }); nextBtn.addEventListener('click', () => { if (currentTab < tabs.length - 1) switchTab(currentTab + 1); }); prevBtn.addEventListener('click', () => { if (currentTab > 0) switchTab(currentTab - 1); }); // --- Event Listeners --- configForm.addEventListener('submit', handleAddCourse); addExpBtn.addEventListener('click', handleAddExperience); targetCourseSelect.addEventListener('change', handleCourseSelectChange); generateBtn.addEventListener('click', () => { renderReviewSheet(); switchTab(1); // Switch to review tab }); pdfDownloadBtn.addEventListener('click', downloadPDF); // --- Initial Setup --- courses.push(sampleCourse); renderConfigTable(); populateTargetCourseDropdown(); updateNavButtons(); // This also re-orders the tabs });