No discoveries added yet.
";
return;
}
discoveries.forEach(d => {
const itemEl = document.createElement("div");
itemEl.className = "sdtg-config-list-item";
itemEl.dataset.id = d.id;
itemEl.innerHTML = `
[${d.year}] ${escapeHTML(d.name)} (${escapeHTML(d.field)})
`;
configList.appendChild(itemEl);
});
}
// --- Dashboard Management ---
function renderDashboard() {
if (!dashboardTbody) return;
dashboardTbody.innerHTML = ""; // Clear
if (discoveries.length === 0) {
dashboardTbody.innerHTML = `
|
No discoveries logged yet. Add an entry in the Configuration tab.
|
`;
return;
}
discoveries.forEach((d, index) => {
const tr = document.createElement('tr');
tr.dataset.id = d.id;
tr.innerHTML = `
${index + 1} |
|
|
|
|
|
|
`;
dashboardTbody.appendChild(tr);
});
setupDashboardListeners();
}
/**
* Attaches listeners to the dashboard table elements
*/
function setupDashboardListeners() {
const table = dashboardTbody;
if (!table) return;
// Event delegation for removal
table.addEventListener('click', (e) => {
if (e.target.dataset.action === 'remove-dash-item') {
const tr = e.target.closest('tr');
discoveries.splice(discoveries.findIndex(d => d.id === tr.dataset.id), 1);
// Re-render entirely to renumber and update state
renderDashboard();
updateConfigListDisplay();
}
});
// Event delegation for input/change updates
table.addEventListener('input', handleDashboardUpdate);
table.addEventListener('change', 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 dId = tr.dataset.id;
const discovery = discoveries.find(d => d.id === dId);
if (!discovery) return;
const field = target.dataset.field;
if (!field) return;
// Update the master state array
if (field === 'year') {
discovery[field] = parseInt(target.value) || discovery[field];
} else {
discovery[field] = target.value;
}
// Optional: Update config list display immediately
updateConfigListDisplay();
}
/**
* 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;
}
if (discoveries.length === 0) {
alert("The log is empty. Please add discoveries before downloading.");
return;
}
try {
const { jsPDF } = window.jspdf;
const doc = new jsPDF("l", "pt", "a4"); // Landscape for wide table
const margin = 40;
doc.setFontSize(18);
doc.setFont(undefined, 'bold');
doc.text("Scientific Discovery Log", margin, margin);
doc.setFontSize(10);
doc.setFont(undefined, 'normal');
doc.text(`Generated on: ${new Date().toLocaleDateString('en-US')}`, margin, margin + 20);
const tableHead = [['#', 'Name/Title', 'Year', 'Scientist(s)', 'Field', 'Impact Summary']];
// Use the current state of the 'discoveries' array (which is kept in sync with the dashboard)
const tableBody = discoveries.map((d, index) => [
index + 1,
d.name,
d.year,
d.scientist,
d.field,
d.impact
]);
doc.autoTable({
startY: margin + 40,
head: tableHead,
body: tableBody,
theme: 'striped',
headStyles: { fillColor: [0, 115, 230], textColor: [255, 255, 255], fontSize: 9 },
styles: { fontSize: 8, cellPadding: 3, overflow: 'linebreak' },
columnStyles: {
0: { cellWidth: 20, halign: 'center' },
1: { cellWidth: 120 },
2: { cellWidth: 40, halign: 'center' },
3: { cellWidth: 100 },
4: { cellWidth: 80 },
5: { cellWidth: 'auto' }
},
margin: { left: margin, right: margin }
});
doc.save("Scientific_Discovery_Log.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 (addDiscoveryForm) {
addDiscoveryForm.addEventListener("submit", handleAddDiscovery);
}
if (configList) {
configList.addEventListener("click", handleRemoveConfigItem);
}
// PDF Button
if (pdfBtn) {
pdfBtn.addEventListener("click", downloadPDF);
}
// Initial config list display
updateConfigListDisplay();
// Initial State: Generate dashboard with samples
renderDashboard();
showTab("sdtg-tab-dashboard");
});