No tasks defined.
';
}
rstg_data.tasks.forEach(task => {
const role = rstg_data.roles.find(r => r.id === task.roleId);
const roleName = role ? role.name : 'Unknown Role';
rstg_allTasksList.innerHTML += `
${task.desc} (${roleName})
Priority: ${task.priority}, Points: ${task.points}
`;
});
}
window.rstg_addRole = function(event) {
event.preventDefault();
if (!rstg_newRoleName) return;
const name = rstg_newRoleName.value.trim();
if (name) {
const newId = rstg_data.roles.length > 0 ? Math.max(...rstg_data.roles.map(r => r.id)) + 1 : 1;
rstg_data.roles.push({ id: newId, name: name });
rstg_newRoleName.value = '';
rstg_renderAllRoles();
rstg_renderConfigUI();
}
}
window.rstg_deleteRole = function(roleId) {
// Confirmation before deleting
if (!confirm(`Are you sure you want to delete this role? All associated tasks (${rstg_data.tasks.filter(t => t.roleId === roleId).length}) will also be deleted.`)) {
return;
}
rstg_data.roles = rstg_data.roles.filter(r => r.id !== roleId);
// Also delete associated tasks
rstg_data.tasks = rstg_data.tasks.filter(t => t.roleId !== roleId);
rstg_renderAllRoles();
rstg_renderConfigUI();
rstg_handleRoleChange(); // Update dashboard
}
window.rstg_addTask = function(event) {
event.preventDefault();
if (!rstg_taskRoleSelect || !rstg_newTaskDesc || !rstg_newTaskPriority || !rstg_newTaskPoints) return;
const roleId = parseInt(rstg_taskRoleSelect.value);
const desc = rstg_newTaskDesc.value.trim();
const priority = rstg_newTaskPriority.value;
const points = parseInt(rstg_newTaskPoints.value);
if (roleId && desc && priority && points > 0) {
const newId = rstg_data.tasks.length > 0 ? Math.max(...rstg_data.tasks.map(t => t.id)) + 1 : 101;
rstg_data.tasks.push({ id: newId, roleId, desc, priority, points, status: 'pending' });
// Reset form
rstg_newTaskDesc.value = '';
rstg_newTaskPoints.value = '10';
rstg_newTaskPriority.value = 'Medium';
rstg_renderConfigUI();
rstg_handleRoleChange(); // Update dashboard
}
}
window.rstg_deleteTask = function(taskId) {
rstg_data.tasks = rstg_data.tasks.filter(t => t.id !== taskId);
rstg_renderConfigUI();
rstg_handleRoleChange(); // Update dashboard
}
// --- TAB & NAVIGATION FUNCTIONS ---
window.rstg_switchTab = function(tabName) {
rstg_currentTab = tabName;
rstg_tabContents.forEach(content => {
content.classList.remove('rstg-active');
});
rstg_tabs.forEach(tab => {
tab.classList.remove('rstg-active');
});
const activeContent = document.getElementById(`rstg-${tabName}-tab`);
const activeTab = document.querySelector(`.rstg-tab-button[onclick="rstg_switchTab('${tabName}')"]`);
if (activeContent) activeContent.classList.add('rstg-active');
if (activeTab) activeTab.classList.add('rstg-active');
rstg_updateNavButtons();
}
window.rstg_navigateTabs = function(direction) {
const tabNames = ['dashboard', 'config'];
const currentIndex = tabNames.indexOf(rstg_currentTab);
if (direction === 'next' && currentIndex < tabNames.length - 1) {
rstg_switchTab(tabNames[currentIndex + 1]);
} else if (direction === 'prev' && currentIndex > 0) {
rstg_switchTab(tabNames[currentIndex - 1]);
}
}
function rstg_updateNavButtons() {
if (!rstg_prevBtn || !rstg_nextBtn) return;
if (rstg_currentTab === 'dashboard') {
rstg_prevBtn.style.visibility = 'hidden';
rstg_nextBtn.style.visibility = 'visible';
} else if (rstg_currentTab === 'config') {
rstg_prevBtn.style.visibility = 'visible';
rstg_nextBtn.style.visibility = 'hidden';
}
}
// --- PDF GENERATION ---
window.rstg_generatePdf = function() {
// Check if jsPDF and autoTable are loaded
if (typeof jspdf === 'undefined' || typeof jspdf.jsPDF === 'undefined') {
alert('Error: PDF generation library (jsPDF) not loaded.');
return;
}
if (typeof window.jspdf.plugin.autotable === 'undefined') {
alert('Error: PDF generation library (jsPDF-AutoTable) not loaded.');
return;
}
try {
const { jsPDF } = jspdf;
const doc = new jsPDF();
const selectedRoleId = rstg_roleSelect ? rstg_roleSelect.value : null;
const selectedRole = rstg_data.roles.find(r => r.id == selectedRoleId);
if (!selectedRole) {
alert('Please select a role first.');
return;
}
// Get data for PDF
const tasks = rstg_data.tasks.filter(task => task.roleId == selectedRoleId);
const totalPoints = tasks.reduce((sum, task) => sum + task.points, 0);
const achievedPoints = tasks
.filter(task => task.status === 'completed')
.reduce((sum, task) => sum + task.points, 0);
// --- PDF Content ---
doc.setFont('helvetica', 'bold');
doc.setFontSize(20);
doc.setTextColor(40);
doc.text("Role-Specific Task Progress Report", 105, 20, { align: 'center' });
doc.setFont('helvetica', 'normal');
doc.setFontSize(16);
doc.text(`Role: ${selectedRole.name}`, 14, 35);
doc.setFontSize(14);
doc.text(`Total Progress: ${achievedPoints} / ${totalPoints} Points`, 14, 45);
// PDF Table
const tableColumn = ["Task Description", "Priority", "Points", "Status"];
const tableRows = [];
tasks.forEach(task => {
const taskData = [
task.desc,
task.priority,
task.points,
task.status.charAt(0).toUpperCase() + task.status.slice(1) // Capitalize status
];
tableRows.push(taskData);
});
// Auto-generate table
doc.autoTable({
head: [tableColumn],
body: tableRows,
startY: 55,
theme: 'striped', // 'striped', 'grid', 'plain'
headStyles: {
fillColor: [0, 115, 230], // --rstg-primary-color
textColor: [255, 255, 255] // --rstg-text-light
},
styles: {
font: 'helvetica',
cellPadding: 3,
},
alternateRowStyles: {
fillColor: [240, 240, 240] // --rstg-secondary-color
},
// Apply conditional styling for 'Completed' status
didDrawCell: (data) => {
if (data.column.index === 3 && data.cell.section === 'body') {
if(data.cell.text[0] === 'Completed') {
doc.setFont('helvetica', 'bold');
doc.setTextColor(40, 167, 69); // --rstg-success-color
} else if (data.cell.text[0] === 'Pending') {
doc.setFont('helvetica', 'normal');
doc.setTextColor(255, 193, 7); // --rstg-pending-color
}
}
// Reset text color for other cells
doc.setTextColor(51, 51, 51); // --rstg-text-color
}
});
// --- PDF Download ---
// Generate a filename
const safeRoleName = selectedRole.name.replace(/[^a-z0-9]/gi, '_').toLowerCase();
const fileName = `task_report_${safeRoleName}.pdf`;
doc.save(fileName);
} catch (e) {
console.error("PDF Generation Error: ", e);
alert("An error occurred while generating the PDF.");
}
}
// --- RUN INITIALIZATION ---
rstg_initTool();
}); // End of DOMContentLoaded