`;
libraryList.appendChild(div);
});
}
};
// --- EVENT HANDLERS (TAB 1 - DASHBOARD) ---
logBody.addEventListener('blur', (e) => {
if (e.target.isContentEditable) {
const id = parseInt(e.target.dataset.id, 10);
const prop = e.target.dataset.prop;
const newValue = e.target.textContent.trim();
const itemIndex = presentationLog.findIndex(item => item.id === id);
if (itemIndex > -1 && prop) {
presentationLog[itemIndex][prop] = newValue;
}
}
}, true); // Use capture phase
logBody.addEventListener('click', (e) => {
if (e.target.classList.contains('spp-btn-delete')) {
const id = parseInt(e.target.dataset.id, 10);
// No confirm() per spec
presentationLog = presentationLog.filter(item => item.id !== id);
renderLogTable();
}
});
// PDF for Tab 1 (Log)
downloadLogPdfBtn.addEventListener('click', () => {
if (typeof jspdf === 'undefined' || typeof jspdf.autoTable === 'undefined') {
alert('PDF libraries not loaded. Please check your connection.');
return;
}
const { jsPDF } = jspdf;
const doc = new jsPDF();
const head = [['Title', 'Event', 'Date', 'Status']];
const body = presentationLog.map(item => [item.name, item.event, item.date, item.status]);
doc.setFontSize(18);
doc.text("Saved Presentation Plans Log", 14, 22);
jsPDF.autoTable.default(doc, { startY: 30, head: head, body: body, theme: 'grid' });
doc.save('presentation-plan-log.pdf');
});
// --- EVENT HANDLERS (TAB 2 - BUILDER) ---
const updatePlannedTime = () => {
let totalPlanned = 0;
timeInputs.forEach(input => {
totalPlanned += parseFloat(input.value) || 0;
});
const totalAllotted = parseFloat(totalAllottedInput.value) || 0;
const remaining = totalAllotted - totalPlanned;
totalTimeDisplay.textContent = `${totalPlanned} min`;
remainingTimeDisplay.textContent = `${remaining} min`;
// Update color based on remaining time
remainingTimeDisplay.classList.remove('text-green-600', 'text-yellow-600', 'text-red-600', 'text-gray-700');
if (remaining === 0) {
remainingTimeDisplay.classList.add('text-green-600');
} else if (remaining < 0) {
remainingTimeDisplay.classList.add('text-red-600');
} else if (remaining < totalAllotted * 0.1) {
remainingTimeDisplay.classList.add('text-yellow-600');
} else {
remainingTimeDisplay.classList.add('text-gray-700');
}
};
document.getElementById('spp-builder-tab').addEventListener('input', (e) => {
if (e.target.classList.contains('spp-time-input') || e.target.id === 'spp-total-allotted') {
updatePlannedTime();
}
});
saveToLogBtn.addEventListener('click', () => {
const name = titleInput.value.trim();
const event = eventInput.value.trim();
if (!name) {
alert('Please enter a Presentation Title to save to the log.');
return;
}
const newId = (presentationLog.length > 0 ? Math.max(...presentationLog.map(i => i.id)) : 0) + 1;
presentationLog.push({
id: newId,
name: name,
event: event || 'N/A',
date: new Date().toISOString().split('T')[0],
status: "Draft"
});
renderLogTable();
// Switch to dashboard (Spec II.B.4.o)
tabs[0].click();
});
// PDF for Tab 2 (Proposal)
downloadPlanPdfBtn.addEventListener('click', () => {
if (typeof jspdf === 'undefined') {
alert('PDF library not loaded. Please check your connection.');
return;
}
try {
const { jsPDF } = jspdf;
const doc = new jsPDF();
const margin = 15;
const maxWidth = doc.internal.pageSize.width - (margin * 2);
let y = 22; // Start y-position
// Helper to add a section with line wrapping
const addSection = (title, content, time) => {
if (!content && !time) return; // Skip empty sections
// Check for page break
const titleHeight = 10;
const contentLines = content ? doc.splitTextToSize(content, maxWidth - 25) : ['']; // Indent content
const contentHeight = (contentLines.length * 5) + 8;
if (y + titleHeight + contentHeight > doc.internal.pageSize.height - margin) {
doc.addPage();
y = 22;
}
doc.setFontSize(14);
doc.setFont('helvetica', 'bold');
doc.setTextColor('#007bff'); // Blue title
doc.text(title, margin, y);
if (time) {
doc.setFontSize(11);
doc.setFont('helvetica', 'italic');
doc.setTextColor('#555555');
doc.text(`(${time} min)`, doc.internal.pageSize.width - margin, y, { align: 'right' });
}
y += titleHeight;
if(content) {
doc.setFontSize(11);
doc.setFont('helvetica', 'normal');
doc.setTextColor('#333333');
doc.text(contentLines, margin + 5, y); // Indent content
y += (contentLines.length * 5) + 8; // 5 is line height, 8 is padding
} else {
y += 8;
}
};
// --- Build the PDF ---
doc.setFontSize(20);
doc.setFont('helvetica', 'bold');
doc.setTextColor('#333333');
const title = titleInput.value || "Untitled Presentation";
const titleLines = doc.splitTextToSize(title, maxWidth);
doc.text(titleLines, margin, y);
y += (titleLines.length * 8) + 5;
doc.setFontSize(12);
doc.setFont('helvetica', 'normal');
doc.setTextColor('#555555');
const event = eventInput.value || "No Event";
doc.text(event, margin, y);
y += 10;
doc.setDrawColor(200, 200, 200);
doc.line(margin, y, doc.internal.pageSize.width - margin, y); // Horizontal line
y += 10;
// Add sections
const times = Array.from(timeInputs).map(input => input.value);
addSection("Introduction / Background", sectionInputs.Introduction.value, times[0]);
addSection("Methods / Approach", sectionInputs.Methods.value, times[1]);
addSection("Results / Key Findings", sectionInputs.Results.value, times[2]);
addSection("Conclusion / Future Work", sectionInputs.Conclusion.value, times[3]);
addSection("Acknowledgements / Q&A", sectionInputs.Acknowledgements.value, times[4]);
// Add summary
y += 5;
doc.line(margin, y, doc.internal.pageSize.width - margin, y);
y += 10;
doc.setFontSize(12);
doc.setFont('helvetica', 'bold');
doc.setTextColor('#333333');
doc.text(`Total Time Planned: ${totalTimeDisplay.textContent}`, margin, y);
doc.text(`Time Remaining: ${remainingTimeDisplay.textContent}`, doc.internal.pageSize.width - margin, y, { align: 'right' });
doc.save('presentation-plan.pdf');
} catch(e) {
console.error('SGP Tool: Error generating plan PDF:', e);
alert('An error occurred while generating the PDF.');
}
});
// --- EVENT HANDLERS (TAB 3 - LIBRARY) ---
filterSection.addEventListener('change', renderLibrary);
libraryList.addEventListener('click', (e) => {
const btn = e.target.closest('.spp-btn-add');
if (!btn) return;
const id = parseInt(btn.dataset.id, 10);
const prompt = promptDatabase.find(p => p.id === id);
if (!prompt) return;
const targetTextarea = sectionInputs[prompt.section];
if (targetTextarea) {
targetTextarea.value += (targetTextarea.value ? '\n\n' : '') + prompt.content;
// Switch to builder (Tab 2)
tabs[1].click();
}
});
// --- EVENT HANDLERS (TAB 4 - CONFIG) ---
addBlockBtn.addEventListener('click', () => {
const name = newNameInput.value.trim();
const section = newSectionSelect.value;
const content = newContentInput.value.trim();
if (!name || !section || !content) {
alert('Please fill in all fields.');
return;
}
const newId = (promptDatabase.length > 0 ? Math.max(...promptDatabase.map(p => p.id)) : 0) + 1;
promptDatabase.push({ id: newId, name, section, content });
renderConfigTable();
configForm.reset();
});
configBody.addEventListener('click', (e) => {
if (e.target.classList.contains('spp-btn-delete')) {
const id = parseInt(e.target.dataset.id, 10);
// No confirm() per spec
promptDatabase = promptDatabase.filter(item => item.id !== id);
renderConfigTable();
}
});
// --- INITIALIZATION ---
const init = () => {
// Initial Renders
renderLogTable();
renderConfigTable();
updatePlannedTime();
// Set up tabs
updateNavButtons();
// Show the first tab on load
if (tabs.length > 0) {
sppShowTab('spp-dashboard-tab', tabs[0]);
}
};
init();
});
