';
return;
}
// Sort by date, most recent first
const sortedData = [...attentionData].sort((a, b) => new Date(b.date) - new Date(a.date));
sortedData.forEach((entry, index) => {
// Find original index to allow editing/deleting unsorted data
const originalIndex = attentionData.indexOf(entry);
const row = document.createElement('tr');
row.innerHTML = `
${entry.date}
${entry.task}
${entry.category}
${entry.duration}
${entry.focus}
`;
dataTableBody.appendChild(row);
});
},
// --- DATA MANIPULATION ---
logSession() {
if (!logTaskName || !logDuration || !logDate) return;
const newEntry = {
date: logDate.value,
task: logTaskName.value,
category: logTaskCategory.value,
duration: parseInt(logDuration.value, 10),
focus: logFocusLevel.value
};
// Validation
if (!newEntry.date || !newEntry.task || isNaN(newEntry.duration) || newEntry.duration <= 0) {
alert("Please fill in all fields correctly. Duration must be a positive number.");
return;
}
attentionData.push(newEntry);
// Re-render
this.renderDashboard();
this.renderDataTable();
// Reset form
if (logForm) logForm.reset();
logDate.value = new Date().toISOString().split('T')[0];
// Navigate to Dashboard
currentTabIndex = 0;
showAstTab(null, 'ast-tab-1');
// Manually trigger the class change on the first tab link
document.querySelector('.ast-container .ast-tab-link').classList.add('active');
},
showEditModal(index) {
if (index < 0 || index >= attentionData.length || !editModal) return;
currentEditIndex = index;
const entry = attentionData[index];
editIndexInput.value = index;
editTaskName.value = entry.task;
editTaskCategory.value = entry.category;
editDuration.value = entry.duration;
editFocusLevel.value = entry.focus;
editDate.value = entry.date;
editModal.style.display = "block";
},
hideEditModal() {
if (editModal) editModal.style.display = "none";
currentEditIndex = null;
},
saveChanges() {
if (currentEditIndex === null || !editTaskName) return;
const updatedEntry = {
date: editDate.value,
task: editTaskName.value,
category: editTaskCategory.value,
duration: parseInt(editDuration.value, 10),
focus: editFocusLevel.value
};
// Validation
if (!updatedEntry.date || !updatedEntry.task || isNaN(updatedEntry.duration) || updatedEntry.duration <= 0) {
alert("Please fill in all fields correctly. Duration must be a positive number.");
return;
}
attentionData[currentEditIndex] = updatedEntry;
this.renderDashboard();
this.renderDataTable();
this.hideEditModal();
},
deleteEntry(index) {
if (index < 0 || index >= attentionData.length) return;
if (confirm("Are you sure you want to delete this log entry?")) {
attentionData.splice(index, 1);
this.renderDashboard();
this.renderDataTable();
}
},
// --- NAVIGATION & PDF ---
navigateTabs(direction) {
let newIndex = currentTabIndex + direction;
// Clamp index
if (newIndex < 0) newIndex = 0;
if (newIndex >= tabs.length) newIndex = tabs.length - 1;
if (newIndex !== currentTabIndex) {
currentTabIndex = newIndex;
tabs[currentTabIndex].click(); // Programmatically click the tab
}
},
downloadPDF() {
// This method uses the browser's print functionality,
// which allows "Save as PDF" and respects print CSS.
// 1. Create a temporary wrapper to satisfy the @media print rules
const printContainer = document.createElement('div');
printContainer.className = 'ast-print-container';
const toolContainer = document.getElementById('ast-container');
// 2. Move the tool into the print wrapper
document.body.appendChild(printContainer);
printContainer.appendChild(toolContainer);
// 3. Add the printing class to the body
document.body.classList.add('ast-printing');
// 4. Trigger the print dialog
window.print();
// 5. Clean up after print dialog (whether printed or cancelled)
// 'onafterprint' is the most reliable way
window.onafterprint = () => {
document.body.classList.remove('ast-printing');
// 6. Move the tool *back* to its original location
// We assume the original location was just before this