`;
generatedTasksListUL.appendChild(li);
generatedCount++;
});
generatedTasksHeader.textContent = `Generated Tasks from "${template.name}"` + (projectName ? ` for "${projectName}"` : '');
generatedTasksSection.style.display = generatedCount > 0 ? 'block' : 'none';
if (generatedCount === 0) {
generatedTasksListUL.innerHTML = '
This template has no sub-tasks defined.';
}
});
// --- PDF Downloads ---
function downloadTemplateDefinition(templateId) {
const template = taskTemplates.find(t => t.id === templateId);
if (!template) { alert('Template not found for download.'); return; }
const { jsPDF } = window.jspdf;
const doc = new jsPDF();
doc.setFontSize(18);
doc.text(`Template Definition: ${template.name}`, 14, 22);
doc.setFontSize(12);
doc.text(`ID: ${template.id}`, 14, 30);
doc.text(`Number of Sub-Tasks: ${template.subTasks ? template.subTasks.length : 0}`, 14, 36);
if (template.subTasks && template.subTasks.length > 0) {
const body = template.subTasks.map((sub, index) => [
index + 1,
sub.description,
sub.priority,
`+${sub.dueOffsetDays}d`,
sub.duration || 'N/A',
sub.value || 'N/A'
]);
doc.autoTable({
startY: 45,
head: [['#', 'Description', 'Priority', 'Due Offset', 'Duration', 'Value']],
body: body,
theme: 'grid'
});
} else {
doc.text('No sub-tasks defined in this template.', 14, 45);
}
doc.save(`Template_${template.name.replace(/\s+/g, '_')}.pdf`);
}
downloadGeneratedTasksPdfBtn.addEventListener('click', () => {
const templateId = selectTemplateToUse.value;
const template = templateId ? taskTemplates.find(t => t.id === templateId) : null;
const projectName = instanceProjectNameInput.value.trim();
const startDateStr = instanceStartDateInput.value;
const { jsPDF } = window.jspdf;
const doc = new jsPDF();
doc.setFontSize(18);
doc.text('Generated Task List', 14, 22);
doc.setFontSize(11);
if (template) doc.text(`From Template: ${template.name}`, 14, 30);
if (projectName) doc.text(`For Project/Reference: ${projectName}`, 14, template ? 36 : 30);
if (startDateStr) doc.text(`Based on Start Date: ${new Date(startDateStr+"T00:00:00").toLocaleDateString()}`, 14, (template || projectName) ? (template && projectName ? 42 : 36) : 30);
const body = [];
generatedTasksListUL.querySelectorAll('.generated-task-item').forEach((li, index) => {
const descElement = li.querySelector('.task-description-generated');
const description = descElement ? descElement.textContent.trim() : 'N/A';
const metaText = li.querySelector('.task-meta').textContent;
const dueDateMatch = metaText.match(/Due: ([\d\/\.]+)/);
const prioMatch = metaText.match(/Prio: (\w+)/);
const durMatch = metaText.match(/Dur: ([^\|\s]+)/);
const valMatch = metaText.match(/Val: (\d+)/);
body.push([
index + 1,
description,
prioMatch ? prioMatch[1] : 'N/A',
dueDateMatch ? dueDateMatch[1] : 'N/A',
durMatch ? durMatch[1] : 'N/A',
valMatch ? valMatch[1] : 'N/A'
]);
});
if (body.length > 0) {
doc.autoTable({
startY: (template || projectName || startDateStr) ? 50 : 30,
head: [['#', 'Description', 'Priority', 'Due Date', 'Duration', 'Value']],
body: body,
theme: 'grid',
headStyles: { fillColor: [0, 123, 255], textColor: 255 }
});
} else {
doc.text('No tasks were generated or are currently displayed.', 14, 50);
}
const safeProjectName = projectName.replace(/\s+/g, '_') || "Tasks";
doc.save(`Generated_${safeProjectName}.pdf`);
});
// --- Initializations ---
renderTemplatesList(); // Includes populating the select for generation
// Default start date is set via HTML value, but could also be set here if needed
})();