In the "Team & Task Input" tab, add the names of your team members. This helps in assigning tasks and organizing the report.
2. Select Reporting Date
Choose the date for which you are reporting status. This is typically the current day for daily reports.
3. Log Task Statuses
For each team member and for the selected date, add task status entries:
Task Description: What task was worked on or is planned?
Status:
Completed Today: Tasks finished on the reporting date.
In Progress: Tasks actively being worked on but not yet finished.
Blocked: Tasks that cannot proceed. Specify the reason in "Blocker Reason".
Planned for Next Period: Tasks scheduled for the next day or reporting cycle.
% Complete: (Optional) The current completion percentage for "In Progress" tasks.
Notes/Updates: Any relevant details, challenges, or accomplishments related to the task.
4. Generate and Review Report
Go to the "View Report" tab and click "Generate/Refresh Report". The tool will compile all entries for the selected date, grouping them by team member and then by status. Review for clarity and completeness.
5. Export to PDF
Once satisfied, use the "Download Report as PDF" button to get a shareable document.
Tips for Good Reports:
Be Timely: Submit reports consistently.
Be Clear and Concise: Use clear language. Get straight to the point.
Highlight Blockers: Make any impediments highly visible.
Focus on Outcomes: Where possible, mention results and impact, not just activities.
Mention Next Steps: "Planned for Next Period" helps in understanding continuity.
×
Add Task Status Entry
`;
attsrTaskStatusEntriesListEl.appendChild(itemEl);
});
}
// Task Status Modal & CRUD
window.attsrOpenTaskStatusModal = function(entryId = null) {
const selectedDateKey = attsrReportingDateInput.value;
if (!selectedDateKey) { alert("Please select a reporting date first."); return; }
if (attsrTeamMembers.length === 0) { alert("Please add team members first in the 'Team & Task Input' tab."); return; }
attsrTaskStatusForm.reset();
attsrTaskStatusEntryIdInput.value = '';
attsrBlockerReasonGroupEl.style.display = 'none'; // Hide by default
attsrTaskBlockerReasonInput.required = false;
attsrTaskPercentCompleteValueEl.textContent = '0%';
if (entryId) {
const entries = attsrDailyTaskStatuses[selectedDateKey] || [];
const entry = entries.find(e => e.id === entryId);
if (entry) {
attsrModalTitleEl.textContent = 'Edit Task Status Entry';
attsrTaskStatusEntryIdInput.value = entry.id;
attsrTaskTeamMemberSelectEl.value = entry.teamMemberId;
attsrTaskDescriptionInput.value = entry.taskDescription;
attsrTaskStatusSelectEl.value = entry.status;
if (entry.status === 'Blocked') {
attsrBlockerReasonGroupEl.style.display = 'block';
attsrTaskBlockerReasonInput.value = entry.blockerReason || '';
attsrTaskBlockerReasonInput.required = true;
}
attsrTaskPercentCompleteInput.value = entry.percentComplete || 0;
attsrTaskPercentCompleteValueEl.textContent = (entry.percentComplete || 0) + '%';
attsrTaskNotesInput.value = entry.notes || '';
}
} else {
attsrModalTitleEl.textContent = 'Add Task Status Entry for ' + attsrFormatDisplayDate(selectedDateKey);
attsrTaskPercentCompleteInput.value = 0; // Default for new
attsrTaskPercentCompleteValueEl.textContent = '0%';
}
attsrTaskStatusModalEl.style.display = 'block';
}
window.attsrCloseModal = (modalId) => {
const modal = document.getElementById(modalId);
if(modal) modal.style.display = 'none';
}
if(attsrTaskStatusSelectEl) attsrTaskStatusSelectEl.addEventListener('change', function() {
if (this.value === 'Blocked') {
attsrBlockerReasonGroupEl.style.display = 'block';
attsrTaskBlockerReasonInput.required = true;
} else {
attsrBlockerReasonGroupEl.style.display = 'none';
attsrTaskBlockerReasonInput.required = false;
}
});
if(attsrTaskStatusForm) attsrTaskStatusForm.addEventListener('submit', function(e) {
e.preventDefault();
const selectedDateKey = attsrReportingDateInput.value;
if (!selectedDateKey) { alert("Error: No reporting date selected."); return; }
if (!attsrDailyTaskStatuses[selectedDateKey]) {
attsrDailyTaskStatuses[selectedDateKey] = [];
}
const entryId = attsrTaskStatusEntryIdInput.value;
const entryData = {
taskDescription: attsrTaskDescriptionInput.value.trim(),
teamMemberId: attsrTaskTeamMemberSelectEl.value,
status: attsrTaskStatusSelectEl.value,
blockerReason: attsrTaskStatusSelectEl.value === 'Blocked' ? attsrTaskBlockerReasonInput.value.trim() : "",
percentComplete: parseInt(attsrTaskPercentCompleteInput.value),
notes: attsrTaskNotesInput.value.trim()
};
if (!entryData.taskDescription || !entryData.teamMemberId) {
alert("Task description and team member are required."); return;
}
if (entryData.status === 'Blocked' && !entryData.blockerReason) {
alert("Blocker reason is required when status is 'Blocked'."); return;
}
if (entryId) { // Editing
const index = attsrDailyTaskStatuses[selectedDateKey].findIndex(e => e.id === entryId);
if (index > -1) {
attsrDailyTaskStatuses[selectedDateKey][index] = { ...attsrDailyTaskStatuses[selectedDateKey][index], ...entryData };
}
} else { // Adding new
const newEntry = { id: 'attsr-entry-' + Date.now(), ...entryData };
attsrDailyTaskStatuses[selectedDateKey].push(newEntry);
}
attsrSaveDailyTaskStatuses();
attsrRenderTaskStatusEntries(selectedDateKey);
attsrCloseModal('attsrTaskStatusModal');
});
window.attsrDeleteTaskStatusEntry = function(entryId) {
const selectedDateKey = attsrReportingDateInput.value;
if (!selectedDateKey || !attsrDailyTaskStatuses[selectedDateKey]) return;
if (confirm('Are you sure you want to delete this task status entry?')) {
attsrDailyTaskStatuses[selectedDateKey] = attsrDailyTaskStatuses[selectedDateKey].filter(e => e.id !== entryId);
attsrSaveDailyTaskStatuses();
attsrRenderTaskStatusEntries(selectedDateKey);
}
}
// --- Report Generation ---
window.attsrGenerateReport = function() {
if (!attsrReportOutputEl) return;
const selectedDateKey = attsrReportingDateInput.value;
if (!selectedDateKey) {
attsrReportOutputEl.innerHTML = '
Please select a reporting date on the "Team & Task Input" tab first.
';
if(attsrDownloadPdfBtn) attsrDownloadPdfBtn.style.display = 'none';
return;
}
let reportHTML = '';
const entriesByMember = {};
attsrTeamMembers.forEach(member => { // Ensure all team members are listed even if no tasks
entriesByMember[member.id] = { name: member.name, tasksByStatus: {
"Completed Today": [], "In Progress": [], "Blocked": [], "Planned for Next Period": []
}};
});
entries.forEach(entry => {
if (entriesByMember[entry.teamMemberId]) {
if (entriesByMember[entry.teamMemberId].tasksByStatus[entry.status]) {
entriesByMember[entry.teamMemberId].tasksByStatus[entry.status].push(entry);
}
}
});
for (const memberId in entriesByMember) {
const memberData = entriesByMember[memberId];
let memberHTML = `
${memberData.name}
`;
let hasTasksForMember = false;
for (const status in memberData.tasksByStatus) {
if (memberData.tasksByStatus[status].length > 0) {
hasTasksForMember = true;
memberHTML += `