Role-Specific Task Games

Role-Specific Task Games

Your Progress

0 / 0 Points

Manage Roles

Existing Roles

Manage Tasks

Existing Tasks

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