Task Prioritization Assistant
Add & Manage Tasks
Prioritized View
Add New Task
Current Task List
Eisenhower Matrix
Q1: Do First (Urgent & Important)
Q2: Schedule (Important, Not Urgent)
Q3: Delegate (Urgent, Not Important)
Q4: Eliminate/Reconsider (Not Urgent & Not Important)
Ranked Task List (by Priority Score)
Notes: ${task.notes.substring(0,100)}${task.notes.length > 100 ? '...' : ''}
${task.description}
Imp: ${PRIORITY_MAP[task.importance]} Urg: ${PRIORITY_MAP[task.urgency]} Due: ${formatDate(task.dueDate)}
${notesPreview}Due: ${formatDate(task.dueDate)}` : ''}`; ulElement.appendChild(li); }); } function renderRankedList(rankedTasks) { rankedListViewUL.innerHTML = ''; if (rankedTasks.length === 0) { rankedListViewUL.innerHTML = '
${task.description} (Score: ${task.priorityScore})
`;
rankedListViewUL.appendChild(li);
});
}
// --- PDF Export ---
downloadPrioritizedPdfBtn.addEventListener('click', () => {
const currentView = viewToggleSelect.value;
const { jsPDF } = window.jspdf;
const doc = new jsPDF('p', 'pt', 'a4');
const margin = 40;
let yPos = margin;
const pageWidth = doc.internal.pageSize.getWidth();
const textWidth = pageWidth - (2 * margin);
doc.setFontSize(18);
doc.setTextColor(varToRGB('--primary-color').r, varToRGB('--primary-color').g, varToRGB('--primary-color').b);
doc.text('Task Prioritization Report', pageWidth / 2, yPos, { align: 'center' });
yPos += 25;
doc.setFontSize(12);
doc.setTextColor(100);
doc.text(`View Mode: ${currentView === 'matrix' ? 'Eisenhower Matrix' : 'Ranked List'}`, pageWidth / 2, yPos, { align: 'center' });
yPos += 15;
doc.setFontSize(10);
doc.text(`Report Generated: ${new Date().toLocaleString()}`, pageWidth / 2, yPos, { align: 'center' });
yPos += 30;
if (tasks.length === 0) {
doc.text('No tasks were available to prioritize for this report.', margin, yPos);
doc.save('Task_Prioritization_Report_Empty.pdf');
return;
}
const tasksWithScoresForPdf = tasks.map(task => ({ ...task, priorityScore: calculatePriorityScore(task) }));
if (currentView === 'matrix') {
const quadrantsData = {
q1: { title: 'Q1: Do First (Urgent & Important)', tasks: [], color: varToRGB('--q1-do-border') },
q2: { title: 'Q2: Schedule (Important, Not Urgent)', tasks: [], color: varToRGB('--q2-schedule-border') },
q3: { title: 'Q3: Delegate (Urgent, Not Important)', tasks: [], color: varToRGB('--q3-delegate-border') },
q4: { title: 'Q4: Eliminate/Reconsider (Not Urgent & Not Important)', tasks: [], color: varToRGB('--q4-eliminate-border') }
};
tasksWithScoresForPdf.forEach(task => {
const imp = parseInt(task.importance); const urg = parseInt(task.urgency);
if (imp >= 2 && urg >= 2) quadrantsData.q1.tasks.push(task);
else if (imp >= 2 && urg === 1) quadrantsData.q2.tasks.push(task);
else if (imp === 1 && urg >= 2) quadrantsData.q3.tasks.push(task);
else if (imp === 1 && urg === 1) quadrantsData.q4.tasks.push(task);
});
const sortFnPdf = (a,b) => b.priorityScore - a.priorityScore;
for (const qKey in quadrantsData) {
quadrantsData[qKey].tasks.sort(sortFnPdf);
}
for (const qKey in quadrantsData) {
const quadrant = quadrantsData[qKey];
if (yPos > doc.internal.pageSize.getHeight() - 60 && quadrant.tasks.length > 0) { doc.addPage(); yPos = margin; }
doc.setFontSize(14);
doc.setTextColor(quadrant.color.r, quadrant.color.g, quadrant.color.b);
doc.text(quadrant.title, margin, yPos);
yPos += 20;
if (quadrant.tasks.length > 0) {
const body = quadrant.tasks.map(t => [
t.description,
PRIORITY_MAP[t.importance],
PRIORITY_MAP[t.urgency],
t.priorityScore,
formatDate(t.dueDate),
t.notes || ''
]);
doc.autoTable({
startY: yPos, head: [['Task', 'Imp.', 'Urg.', 'Score', 'Due', 'Notes']], body: body,
theme: 'grid', headStyles: { fillColor: [200,200,200], textColor: 20 },
columnStyles: { 0: {cellWidth: 150}, 5: {cellWidth: 120} }
});
yPos = doc.lastAutoTable.finalY + 15;
} else {
doc.setFontSize(10); doc.setTextColor(100);
doc.text('No tasks in this quadrant.', margin + 5, yPos);
yPos += 20;
}
yPos += 5; // Small gap between quadrants
}
} else { // Ranked List View
const rankedTasksForPdf = [...tasksWithScoresForPdf].sort((a,b) => b.priorityScore - a.priorityScore);
doc.setFontSize(14);
doc.setTextColor(varToRGB('--primary-color').r, varToRGB('--primary-color').g, varToRGB('--primary-color').b);
doc.text('Ranked Task List', margin, yPos);
yPos += 20;
const body = rankedTasksForPdf.map(t => [
t.priorityScore,
t.description,
PRIORITY_MAP[t.importance],
PRIORITY_MAP[t.urgency],
formatDate(t.dueDate),
t.notes || ''
]);
doc.autoTable({
startY: yPos, head: [['Score', 'Task', 'Imp.', 'Urg.', 'Due', 'Notes']], body: body,
theme: 'grid', headStyles: { fillColor: [200,200,200], textColor: 20 },
columnStyles: { 1: {cellWidth: 150}, 5: {cellWidth: 120} }
});
}
doc.save('Task_Prioritization_Report.pdf');
});
function varToRGB(varName, asArray = false) {
let colorHex = getComputedStyle(document.documentElement).getPropertyValue(varName).trim();
if (!colorHex.startsWith('#')) { colorHex = '#000000'; } // Default to black if var not found or not hex
const r = parseInt(colorHex.slice(1, 3), 16);
const g = parseInt(colorHex.slice(3, 5), 16);
const b = parseInt(colorHex.slice(5, 7), 16);
return asArray ? [r,g,b] : {r,g,b};
}
// --- Initializations ---
renderTasksList();
// Default to matrix view and trigger initial prioritization if tasks exist
if(tasks.length > 0) {
prioritizeTasksBtn.click(); // Generate initial prioritized view
} else {
eisenhowerMatrixViewDiv.style.display = 'block'; // Show matrix even if empty
rankedListViewDiv.style.display = 'none';
q1ListUL.innerHTML = '
Imp: ${PRIORITY_MAP[task.importance]}
Urg: ${PRIORITY_MAP[task.urgency]}
Due: ${formatDate(task.dueDate)}
${notesPreview}
