No questions added yet.
";
return;
}
questions.forEach(q => {
const itemEl = document.createElement("div");
itemEl.className = "sqag-config-list-item";
itemEl.dataset.id = q.id;
itemEl.innerHTML = `
${escapeHTML(q.topic)}: ${escapeHTML(q.q.substring(0, 50))}...
`;
configQuestionList.appendChild(itemEl);
});
}
// --- Dashboard Management ---
function renderDashboard(isInitial = true) {
// Get config headers
dashTitle.value = configTitle.value;
dashGrade.value = configGrade.value;
// --- Build Dashboard Table HTML ---
if (questions.length === 0) {
dashboardOutput.innerHTML = `
Add questions using the "Question Configuration" tab and then generate the worksheet here.
`;
return;
}
dashboardOutput.innerHTML = `
| # |
Question |
Topic |
Answer (Hidden) |
Action |
`;
// Populate Table Body
const tbody = dashboardOutput.querySelector('#sqag-dash-table tbody');
questions.forEach((q, index) => {
const tr = document.createElement('tr');
tr.dataset.id = q.id;
tr.innerHTML = `
${index + 1} |
|
|
|
|
`;
tbody.appendChild(tr);
});
setupDashboardListeners();
if (!isInitial) showTab('sqag-tab-dashboard');
}
/**
* Attaches listeners to the dashboard elements
*/
function setupDashboardListeners() {
const table = dashboardOutput.querySelector('#sqag-dash-table');
if (!table) return;
// Event delegation for removal
table.addEventListener('click', (e) => {
if (e.target.dataset.action === 'remove-q') {
const tr = e.target.closest('tr');
questions.splice(questions.findIndex(q => q.id === tr.dataset.id), 1);
// Re-render entirely to renumber the questions
renderDashboard(false);
updateConfigQuestionDisplay();
}
});
// Event delegation for input/change updates
table.addEventListener('input', handleDashboardUpdate);
}
/**
* Handles updates made directly to the dashboard table cells
*/
function handleDashboardUpdate(e) {
const target = e.target;
const tr = target.closest('tr');
if (!tr) return;
const qId = tr.dataset.id;
const question = questions.find(q => q.id === qId);
if (!question) return;
const field = target.dataset.field;
if (!field) return;
// Update the master state array
question[field] = target.value;
// Optional: Update config list display immediately
updateConfigQuestionDisplay();
}
/**
* Generates a PDF report from the dashboard data
*/
function downloadPDF() {
if (typeof window.jspdf === 'undefined' || typeof window.jspdf.jsPDF.autoTable === 'undefined') {
alert("Error: PDF libraries could not be loaded. Please try again.");
return;
}
const table = dashboardOutput.querySelector('#sqag-dash-table');
if (!table) {
alert("Please generate the worksheet before downloading.");
return;
}
try {
const { jsPDF } = window.jspdf;
const worksheetDoc = new jsPDF("p", "pt", "a4");
const answerKeyDoc = new jsPDF("p", "pt", "a4");
const margin = 40;
const title = dashTitle.value || "Science Worksheet";
const grade = dashGrade.value || "Grade Level";
const tableHead = [['#', 'Question', 'Topic']];
const tableHeadKey = [['#', 'Question', 'Answer', 'Topic']];
const tableBody = [];
const tableBodyKey = [];
// 1. Extract data from the editable dashboard table
Array.from(table.querySelectorAll('tbody tr')).forEach((tr, index) => {
const q = tr.querySelector('[data-field="q"]').value;
const a = tr.querySelector('[data-field="a"]').value;
const topic = tr.querySelector('[data-field="topic"]').value;
tableBody.push([
index + 1,
q,
topic
]);
tableBodyKey.push([
index + 1,
q,
a,
topic
]);
});
// --- Worksheet PDF ---
worksheetDoc.setFontSize(18);
worksheetDoc.setFont(undefined, 'bold');
worksheetDoc.text(title, worksheetDoc.internal.pageSize.getWidth() / 2, margin, { align: 'center' });
worksheetDoc.setFontSize(12);
worksheetDoc.setFont(undefined, 'normal');
worksheetDoc.text(`Level: ${grade}`, margin, margin + 30);
worksheetDoc.text('Name: ______________________', worksheetDoc.internal.pageSize.getWidth() - margin, margin + 30, { align: 'right' });
worksheetDoc.autoTable({
startY: margin + 60,
head: tableHead,
body: tableBody.map(row => [row[0], row[1], row[2]]),
theme: 'grid',
headStyles: { fillColor: [0, 115, 230], textColor: [255, 255, 255], fontSize: 10 },
styles: { fontSize: 9, cellPadding: 8, overflow: 'linebreak' },
columnStyles: { 0: { cellWidth: 30, halign: 'center' }, 1: { cellWidth: 'auto' }, 2: { cellWidth: 80 } },
margin: { left: margin, right: margin }
});
worksheetDoc.save(`${title.replace(/ /g,"_")}_Worksheet.pdf`);
// --- Answer Key PDF ---
answerKeyDoc.setFontSize(18);
answerKeyDoc.setFont(undefined, 'bold');
answerKeyDoc.text(`${title} - ANSWER KEY`, answerKeyDoc.internal.pageSize.getWidth() / 2, margin, { align: 'center' });
answerKeyDoc.setFontSize(12);
answerKeyDoc.setFont(undefined, 'normal');
answerKeyDoc.text(`Level: ${grade}`, margin, margin + 30);
answerKeyDoc.autoTable({
startY: margin + 50,
head: tableHeadKey,
body: tableBodyKey,
theme: 'grid',
headStyles: { fillColor: [40, 167, 69], textColor: [255, 255, 255], fontSize: 10 },
styles: { fontSize: 9, cellPadding: 8, overflow: 'linebreak' },
columnStyles: { 0: { cellWidth: 30, halign: 'center' }, 1: { cellWidth: 150 }, 2: { cellWidth: 'auto' }, 3: { cellWidth: 70 } },
margin: { left: margin, right: margin }
});
answerKeyDoc.save(`${title.replace(/ /g,"_")}_AnswerKey.pdf`);
} catch (error) {
console.error("PDF Generation Error:", error);
alert("An error occurred during PDF creation. Please ensure all data fields are filled correctly.");
}
}
/**
* Helper to escape HTML
*/
function escapeHTML(str) {
if (!str) return "";
return str
.replace(/&/g, "&")
.replace(//g, ">")
.replace(/"/g, """)
.replace(/'/g, "'");
}
// --- 4. INITIALIZATION & EVENT LISTENERS ---
// Tab Listeners
tabButtons.forEach((btn) => {
btn.addEventListener("click", () => showTab(btn.dataset.target));
});
navButtons.forEach((btn) => {
btn.addEventListener("click", () => showTab(btn.dataset.target));
});
// Config Tab Listeners
if (addQuestionForm) {
addQuestionForm.addEventListener("submit", handleAddQuestion);
}
if (configQuestionList) {
configQuestionList.addEventListener("click", handleRemoveQuestion);
}
if (generateBtn) {
generateBtn.addEventListener("click", () => renderDashboard(false));
}
// PDF Button
if (pdfBtn) {
pdfBtn.addEventListener("click", downloadPDF);
}
// Initial config list display
updateConfigQuestionDisplay();
// Initial State: Generate dashboard with samples
renderDashboard();
showTab("sqag-tab-dashboard");
});