Online Multi-Project Collaboration Hub

Multi-Project Collaboration Hub

Projects Overview

Tasks: ${completedTasks} / ${projectTasks.length}

${progress}% Complete

`; dashboardGrid.appendChild(card); }); }; const renderProjectsTab = () => { // Populate selector projectSelector.innerHTML = state.projects.map(p => ``).join(''); if (state.selectedProjectId) { projectSelector.value = state.selectedProjectId; } else if (state.projects.length > 0) { state.selectedProjectId = state.projects[0].id; projectSelector.value = state.selectedProjectId; } // Render tasks for selected project renderTaskTable(); }; const renderTaskTable = () => { tasksTableBody.innerHTML = ''; const selectedProject = state.projects.find(p => p.id == state.selectedProjectId); projectReportTitle.textContent = selectedProject ? `Task List for: ${selectedProject.name}` : 'No Project Selected'; if (!state.selectedProjectId) return; const projectTasks = state.tasks.filter(t => t.projectId == state.selectedProjectId); if (projectTasks.length === 0) { tasksTableBody.innerHTML = `No tasks for this project.`; return; } projectTasks.forEach(task => { const teamMember = state.team.find(tm => tm.id === task.teamMemberId)?.name || 'Unassigned'; const statusClass = task.status === 'Done' ? 'status-done' : task.status === 'In Progress' ? 'status-inprogress' : 'status-todo'; const row = document.createElement('tr'); row.className = 'bg-white border-b'; row.innerHTML = ` ${task.name} ${teamMember} ${task.dueDate} ${task.status} `; tasksTableBody.appendChild(row); }); }; const renderConfigTab = () => { // Render Projects configContainers.projects.innerHTML = ''; state.projects.forEach(p => addConfigRow('project', p)); // Render Team configContainers.team.innerHTML = ''; state.team.forEach(tm => addConfigRow('team', tm)); // Render Tasks configContainers.tasks.innerHTML = ''; state.tasks.forEach(t => addConfigRow('task', t)); }; const addConfigRow = (type, data = {}) => { const container = configContainers[type]; const newRow = document.createElement('div'); newRow.className = 'flex items-center space-x-2 config-row'; let content = ''; switch (type) { case 'project': content = ``; break; case 'team': content = ``; break; case 'task': const projectOptions = state.projects.map(p => ``).join(''); const teamOptions = state.team.map(tm => ``).join(''); content = ` `; break; } newRow.innerHTML = content + ``; newRow.dataset.id = data.id || Date.now(); container.appendChild(newRow); newRow.querySelector('.remove-row-btn').addEventListener('click', () => newRow.remove()); }; // --- DATA & LOGIC FUNCTIONS --- const saveConfiguration = () => { // Save Projects state.projects = Array.from(configContainers.projects.querySelectorAll('.config-row')).map((row, i) => ({ id: i + 1, name: row.querySelector('.data-name').value.trim() })).filter(p => p.name); // Save Team state.team = Array.from(configContainers.team.querySelectorAll('.config-row')).map((row, i) => ({ id: i + 1, name: row.querySelector('.data-name').value.trim() })).filter(tm => tm.name); // Save Tasks state.tasks = Array.from(configContainers.tasks.querySelectorAll('.config-row')).map((row, i) => ({ id: i + 1, name: row.querySelector('.data-name').value.trim(), projectId: parseInt(row.querySelector('.data-project-id').value), teamMemberId: parseInt(row.querySelector('.data-team-id').value), dueDate: row.querySelector('.data-due-date').value, status: row.querySelector('.data-status').value })).filter(t => t.name); alert('Configuration saved successfully!'); renderAll(); }; const switchTab = (tabName) => { state.activeTab = tabName; Object.values(tabs).forEach(tab => { tab.btn.classList.remove('active'); tab.panel.classList.add('hidden'); }); tabs[tabName].btn.classList.add('active'); tabs[tabName].panel.classList.remove('hidden'); updateNavButtons(); }; const updateNavButtons = () => { const tabKeys = Object.keys(tabs); const currentIndex = tabKeys.indexOf(state.activeTab); navButtons.prev.disabled = currentIndex === 0; navButtons.next.disabled = currentIndex === tabKeys.length - 1; }; const handlePdfDownload = () => { const { jsPDF } = window.jspdf; const pdfContent = document.getElementById('pdf-export-area'); html2canvas(pdfContent, { scale: 2, useCORS: true }).then(canvas => { const imgData = canvas.toDataURL('image/png'); const pdf = new jsPDF({ orientation: 'portrait', unit: 'pt', format: 'a4' }); const imgProps = pdf.getImageProperties(imgData); const pdfWidth = pdf.internal.pageSize.getWidth(); const pdfHeight = (imgProps.height * pdfWidth) / imgProps.width; const margin = 40; pdf.addImage(imgData, 'PNG', margin, margin, pdfWidth - (margin * 2), pdfHeight); pdf.save('project-report.pdf'); }); }; const renderAll = () => { renderDashboard(); renderProjectsTab(); renderConfigTab(); }; // --- EVENT LISTENERS --- Object.keys(tabs).forEach(tabName => { tabs[tabName].btn.addEventListener('click', () => switchTab(tabName)); }); navButtons.next.addEventListener('click', () => { const tabKeys = Object.keys(tabs); const currentIndex = tabKeys.indexOf(state.activeTab); if (currentIndex < tabKeys.length - 1) switchTab(tabKeys[currentIndex + 1]); }); navButtons.prev.addEventListener('click', () => { const tabKeys = Object.keys(tabs); const currentIndex = tabKeys.indexOf(state.activeTab); if (currentIndex > 0) switchTab(tabKeys[currentIndex - 1]); }); addButtons.project.addEventListener('click', () => addConfigRow('project')); addButtons.team.addEventListener('click', () => addConfigRow('team')); addButtons.task.addEventListener('click', () => addConfigRow('task')); saveConfigBtn.addEventListener('click', saveConfiguration); projectSelector.addEventListener('change', (e) => { state.selectedProjectId = e.target.value; renderTaskTable(); }); downloadPdfBtn.addEventListener('click', handlePdfDownload); // --- INITIALIZATION --- const init = () => { // Sample Data state.projects = [ { id: 1, name: 'Website Redesign' }, { id: 2, name: 'Q3 Marketing Campaign' }, { id: 3, name: 'Mobile App Launch' } ]; state.team = [ { id: 1, name: 'John Smith' }, { id: 2, name: 'Emily Jones' }, { id: 3, name: 'Michael Williams' } ]; state.tasks = [ { id: 1, name: 'Develop new homepage mockup', projectId: 1, teamMemberId: 2, dueDate: '2025-09-15', status: 'In Progress' }, { id: 2, name: 'Create social media content calendar', projectId: 2, teamMemberId: 2, dueDate: '2025-08-30', status: 'Done' }, { id: 3, name: 'Finalize API documentation', projectId: 3, teamMemberId: 1, dueDate: '2025-09-05', status: 'In Progress' }, { id: 4, name: 'User testing for checkout flow', projectId: 1, teamMemberId: 3, dueDate: '2025-09-20', status: 'To Do' }, { id: 5, name: 'Launch PPC ads for campaign', projectId: 2, teamMemberId: 3, dueDate: '2025-09-01', status: 'To Do' }, ]; state.selectedProjectId = state.projects[0]?.id; renderAll(); switchTab('dashboard'); }; init(); });
Scroll to Top