Please select a reporting date.
';
return;
}
if(attsrCurrentDateDisplayEl) attsrCurrentDateDisplayEl.textContent = attsrFormatDisplayDate(selectedDateKey);
if(attsrReportDateDisplayEl) attsrReportDateDisplayEl.textContent = attsrFormatDisplayDate(selectedDateKey);
attsrRenderTaskStatusEntries(selectedDateKey);
}
function attsrRenderTaskStatusEntries(dateKey) {
if (!attsrTaskStatusEntriesListEl) return;
attsrTaskStatusEntriesListEl.innerHTML = '';
const entries = attsrDailyTaskStatuses[dateKey] || [];
if (entries.length === 0) {
attsrTaskStatusEntriesListEl.innerHTML = '
No task status entries logged for this date.
';
return;
}
entries.forEach(entry => {
const member = attsrTeamMembers.find(m => m.id === entry.teamMemberId);
const itemEl = document.createElement('div');
itemEl.className = 'attsr-list-item';
itemEl.innerHTML = `
${entry.taskDescription}
By: ${member ? member.name : 'Unknown'} | Status: ${entry.status}
${entry.percentComplete !== undefined ? `(${entry.percentComplete}%)` : ''}
${entry.status === 'Blocked' && entry.blockerReason ? `Blocked: ${entry.blockerReason}` : ''}
${entry.notes ? `Notes: ${entry.notes} ` : ''}
Edit
Delete
`;
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(attsrReportDateDisplayEl) attsrReportDateDisplayEl.textContent = "N/A";
if(attsrDownloadPdfBtn) attsrDownloadPdfBtn.style.display = 'none';
return;
}
if(attsrReportDateDisplayEl) attsrReportDateDisplayEl.textContent = attsrFormatDisplayDate(selectedDateKey);
const entries = attsrDailyTaskStatuses[selectedDateKey] || [];
if (entries.length === 0) {
attsrReportOutputEl.innerHTML = '
No task status entries logged for this date.
';
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 += `
${status}
`;
memberData.tasksByStatus[status].forEach(task => {
memberHTML += `${task.taskDescription} ${task.percentComplete !== undefined ? `(${task.percentComplete}%)` : ''}`;
if (status === 'Blocked' && task.blockerReason) {
memberHTML += `Blocked by: ${task.blockerReason} `;
}
if (task.notes) {
memberHTML += `Notes: ${task.notes} `;
}
memberHTML += ` `;
});
memberHTML += ` `;
}
}
if (!hasTasksForMember) {
memberHTML += `
No updates for this period.
`;
}
memberHTML += `
`;
reportHTML += memberHTML;
}
attsrReportOutputEl.innerHTML = reportHTML;
if(attsrDownloadPdfBtn) attsrDownloadPdfBtn.style.display = 'block';
}
// --- PDF Export ---
if(attsrDownloadPdfBtn) attsrDownloadPdfBtn.addEventListener('click', function() {
const selectedDateKey = attsrReportingDateInput.value;
if (!selectedDateKey || !attsrDailyTaskStatuses[selectedDateKey] || attsrDailyTaskStatuses[selectedDateKey].length === 0) {
alert("No data for the selected date to export.");
return;
}
const entries = attsrDailyTaskStatuses[selectedDateKey];
const { jsPDF } = window.jspdf;
const doc = new jsPDF();
const primaryColor = getComputedStyle(document.documentElement).getPropertyValue('--attsr-primary-color').trim();
doc.setFontSize(18);
doc.setTextColor(primaryColor);
doc.text(`Team Task Status Report - ${attsrFormatDisplayDate(selectedDateKey)}`, 14, 22);
let yPos = 35;
const entriesByMember = {};
attsrTeamMembers.forEach(member => {
entriesByMember[member.id] = { name: member.name, tasksByStatus: {
"Completed Today": [], "In Progress": [], "Blocked": [], "Planned for Next Period": []
}};
});
entries.forEach(entry => {
if (entriesByMember[entry.teamMemberId] && entriesByMember[entry.teamMemberId].tasksByStatus[entry.status]) {
entriesByMember[entry.teamMemberId].tasksByStatus[entry.status].push(entry);
}
});
for (const memberId in entriesByMember) {
const memberData = entriesByMember[memberId];
if (yPos > 260) { doc.addPage(); yPos = 20; }
doc.setFontSize(14);
doc.setTextColor(primaryColor);
doc.text(memberData.name, 14, yPos);
yPos += 8;
let memberHasTasks = false;
for (const status in memberData.tasksByStatus) {
if (memberData.tasksByStatus[status].length > 0) {
memberHasTasks = true;
if (yPos > 265) { doc.addPage(); yPos = 20; }
doc.setFontSize(11);
doc.setTextColor(getComputedStyle(document.documentElement).getPropertyValue('--attsr-text-color').trim());
doc.setFont(undefined, 'bold');
doc.text(status, 16, yPos);
yPos += 6;
doc.setFont(undefined, 'normal');
doc.setFontSize(9);
memberData.tasksByStatus[status].forEach(task => {
if (yPos > 270) { doc.addPage(); yPos = 20; }
let taskLine = `\u2022 ${task.taskDescription} ${task.percentComplete !== undefined ? `(${task.percentComplete}%)` : ''}`;
const splitTaskLine = doc.splitTextToSize(taskLine, doc.internal.pageSize.getWidth() - 40);
doc.text(splitTaskLine, 18, yPos);
yPos += splitTaskLine.length * 4;
if (status === 'Blocked' && task.blockerReason) {
if (yPos > 270) { doc.addPage(); yPos = 20; }
const blockerLine = ` Blocked by: ${task.blockerReason}`;
const splitBlocker = doc.splitTextToSize(blockerLine, doc.internal.pageSize.getWidth() - 44);
doc.setTextColor(getComputedStyle(document.documentElement).getPropertyValue('--attsr-danger-color').trim());
doc.text(splitBlocker, 20, yPos);
doc.setTextColor(getComputedStyle(document.documentElement).getPropertyValue('--attsr-text-color').trim());
yPos += splitBlocker.length * 4;
}
if (task.notes) {
if (yPos > 270) { doc.addPage(); yPos = 20; }
const notesLine = ` Notes: ${task.notes}`;
const splitNotes = doc.splitTextToSize(notesLine, doc.internal.pageSize.getWidth() - 44);
doc.setTextColor(120,120,120); // Grey for notes
doc.text(splitNotes, 20, yPos);
doc.setTextColor(getComputedStyle(document.documentElement).getPropertyValue('--attsr-text-color').trim());
yPos += splitNotes.length * 4;
}
yPos += 1; // Small gap between tasks
});
yPos += 3; // Gap after status group
}
}
if (!memberHasTasks) {
if (yPos > 270) { doc.addPage(); yPos = 20; }
doc.setFontSize(9);
doc.setTextColor(120,120,120);
doc.text("No updates for this period.", 18, yPos);
yPos += 5;
}
yPos += 5; // Gap after member block
}
doc.save(`TeamStatusReport_${selectedDateKey}.pdf`);
});
// --- Initialization ---
document.addEventListener('DOMContentLoaded', () => {
const today = new Date(2025, 4, 14); // May 14, 2025, month is 0-indexed
attsrReportingDateInput.value = attsrFormatDateKey(today);
attsrLoadData();
const firstTabButton = document.querySelector('#teamTaskStatusReporterTool .attsr-tab-button');
if (firstTabButton) {
firstTabButton.click();
}
// Close modal if clicked outside
window.addEventListener('click', function(event) {
const modal = document.getElementById('attsrTaskStatusModal');
if (modal && event.target == modal) {
attsrCloseModal('attsrTaskStatusModal');
}
});
// Update progress value display when slider changes in add/edit modal
if(attsrTaskPercentCompleteInput && attsrTaskPercentCompleteValueEl) {
attsrTaskPercentCompleteInput.addEventListener('input', function() {
attsrTaskPercentCompleteValueEl.textContent = this.value + '%';
});
}
});