`).join('');
card.innerHTML = `
`;
projectDashboard.appendChild(card);
});
};
/**
* Populates all forms and configuration inputs.
*/
const populateForms = () => {
// Add Project Form
const deptsCheckboxDiv = document.getElementById('departmentsCheckbox');
deptsCheckboxDiv.innerHTML = departments.map(d => `
`).join('');
const contactSelect = document.getElementById('keyContact');
contactSelect.innerHTML = teamMembers.map(m => ``).join('');
const statusSelect = document.getElementById('projectStatus');
statusSelect.innerHTML = statuses.map(s => ``).join('');
// Configuration Tab
const deptsConfigDiv = document.getElementById('departmentsConfig');
deptsConfigDiv.innerHTML = departments.map((d, i) => ``).join('');
const membersConfigDiv = document.getElementById('teamMembersConfig');
membersConfigDiv.innerHTML = teamMembers.map((m, i) => ``).join('');
};
/**
* Handles new project form submission.
*/
const handleProjectSubmit = (e) => {
e.preventDefault();
const involvedDepts = Array.from(document.querySelectorAll('#departmentsCheckbox input:checked')).map(cb => cb.value);
if (involvedDepts.length === 0) {
alert('Please select at least one department.');
return;
}
const newProject = {
id: nextProjectId++,
title: document.getElementById('projectTitle').value,
involvedDepts: involvedDepts,
contact: document.getElementById('keyContact').value,
status: document.getElementById('projectStatus').value,
description: document.getElementById('projectDescription').value,
updates: []
};
projects.push(newProject);
projectForm.reset();
updateAll();
changeTab(0);
};
/**
* Generates and downloads a professional PDF report of all projects.
*/
const downloadPDF = () => {
const { jsPDF } = window.jspdf;
const doc = new jsPDF();
doc.setFontSize(22);
doc.text('Cross-Department Project Report', 14, 20);
doc.setFontSize(10);
doc.setTextColor(150);
doc.text(`Report generated on: ${new Date().toLocaleDateString()}`, 14, 26);
let yPos = 40;
projects.forEach(project => {
if (yPos > 250) {
doc.addPage();
yPos = 20;
}
doc.setFontSize(16);
doc.setFont('helvetica', 'bold');
doc.setTextColor(0);
doc.text(project.title, 14, yPos);
yPos += 8;
doc.setFontSize(11);
doc.setFont('helvetica', 'normal');
doc.text(`Status: ${project.status} | Contact: ${project.contact}`, 14, yPos);
yPos += 6;
doc.text(`Departments: ${project.involvedDepts.join(', ')}`, 14, yPos);
yPos += 10;
if (project.updates.length > 0) {
const latestUpdate = project.updates[project.updates.length - 1];
doc.setFont('helvetica', 'italic');
doc.setTextColor(100);
const splitText = doc.splitTextToSize(`Latest Update from ${latestUpdate.user}: ${latestUpdate.text}`, 180);
doc.text(splitText, 16, yPos);
yPos += (splitText.length * 5) + 4;
} else {
doc.setFont('helvetica', 'italic');
doc.setTextColor(100);
doc.text('No updates posted yet.', 16, yPos);
yPos += 10;
}
yPos += 8; // Extra space
});
doc.save('coordination-hub-report.pdf');
};
/**
* Updates all dynamic parts of the tool.
*/
const updateAll = () => {
renderDashboard();
populateForms();
updateNavButtons();
};
// --- Event Listeners ---
prevBtn.addEventListener('click', () => changeTab(currentTab - 1));
nextBtn.addEventListener('click', () => changeTab(currentTab + 1));
projectForm.addEventListener('submit', handleProjectSubmit);
pdfDownloadBtn.addEventListener('click', downloadPDF);
addDepartmentBtn.addEventListener('click', () => { departments.push('New Department'); populateForms(); });
addTeamMemberBtn.addEventListener('click', () => { teamMembers.push('New Member (Dept)'); populateForms(); });
saveConfigBtn.addEventListener('click', () => {
departments = Array.from(document.querySelectorAll('#departmentsConfig input')).map(i => i.value).filter(Boolean);
teamMembers = Array.from(document.querySelectorAll('#teamMembersConfig input')).map(i => i.value).filter(Boolean);
updateAll();
alert('Configuration Saved!');
});
// Event delegation for dynamic elements
tabContent.addEventListener('click', e => {
if (e.target.classList.contains('remove-btn')) {
const type = e.target.dataset.type;
const index = parseInt(e.target.dataset.index);
if (type === 'department') departments.splice(index, 1);
if (type === 'member') teamMembers.splice(index, 1);
populateForms();
}
if (e.target.classList.contains('add-update-btn')) {
const card = e.target.closest('.project-card');
const projectId = parseInt(card.dataset.projectId);
const project = projects.find(p => p.id === projectId);
const textarea = card.querySelector('.update-input');
const updateText = textarea.value.trim();
if (project && updateText) {
// In a real app, user would be identified. Here we use the key contact.
project.updates.push({ user: project.contact, text: updateText });
textarea.value = '';
renderDashboard();
}
}
});
// Initial setup
updateAll();
});
${project.title}
${project.status}Contact: ${project.contact}
${project.involvedDepts.map(d => `${d}`).join('')}
${project.description}
Updates
${updatesHtml}
