Post-Production Dashboard

Post-Production Dashboard

Project Overview

Total Projects

0

Overall Progress

0%

Budget Spent

$0

Overdue Tasks

0

Project Status Distribution

Budget vs. Actual Spending

$${Math.abs(remaining).toLocaleString()}

Expense Breakdown

${project.tasks.length > 0 ? project.tasks.map(task => ``).join('') : ``}
Task/ExpenseCost
${task.name}$${task.cost.toLocaleString()}
No expenses logged.
`; container.appendChild(projectElement); }); } // --- EVENT HANDLERS & LOGIC --- // function attachEventListeners() { prevBtn.addEventListener('click', () => changeTab(state.activeTab - 1)); nextBtn.addEventListener('click', () => changeTab(state.activeTab + 1)); addProjectForm.addEventListener('submit', handleAddProject); downloadPdfBtn.addEventListener('click', handleDownloadPdf); } window.changeTab = (tabIndex) => { if (tabIndex < 0 || tabIndex >= tabButtons.length) return; state.activeTab = tabIndex; updateTabUI(); }; function updateTabUI() { tabButtons.forEach((button, index) => { button.classList.toggle('active', index === state.activeTab); button.classList.toggle('inactive', index !== state.activeTab); tabPanes[index].classList.toggle('hidden', index !== state.activeTab); }); prevBtn.disabled = state.activeTab === 0; nextBtn.disabled = state.activeTab === tabButtons.length - 1; prevBtn.classList.toggle('opacity-50', prevBtn.disabled); nextBtn.classList.toggle('opacity-50', nextBtn.disabled); } function handleAddProject(e) { e.preventDefault(); const newProject = { id: Date.now(), name: document.getElementById('project-name').value, budget: parseFloat(document.getElementById('project-budget').value), startDate: document.getElementById('project-start-date').value, endDate: document.getElementById('project-end-date').value, tasks: [] }; state.projects.push(newProject); addProjectForm.reset(); render(); changeTab(1); } window.deleteProject = (projectId) => { if (confirm('Are you sure you want to delete this entire project?')) { state.projects = state.projects.filter(p => p.id !== projectId); render(); } }; window.addTask = (event, projectId) => { const form = event.target; const project = state.projects.find(p => p.id === projectId); if (project) { project.tasks.push({ id: Date.now(), name: form.elements.taskName.value, status: 'Not Started', assignedTo: form.elements.assignedTo.value, dueDate: form.elements.dueDate.value, cost: parseFloat(form.elements.cost.value) }); form.reset(); render(); } }; window.deleteTask = (projectId, taskId) => { const project = state.projects.find(p => p.id === projectId); if (project) { project.tasks = project.tasks.filter(t => t.id !== taskId); render(); } }; window.updateTaskStatus = (projectId, taskId, newStatus) => { const task = state.projects.find(p => p.id === projectId)?.tasks.find(t => t.id === taskId); if (task) { task.status = newStatus; render(); } }; async function handleDownloadPdf() { const downloadBtn = document.getElementById('download-pdf-btn'); if (!downloadBtn || downloadBtn.disabled) return; const originalBtnContent = downloadBtn.innerHTML; downloadBtn.disabled = true; downloadBtn.innerHTML = `Generating PDF...`; try { const { jsPDF } = window.jspdf; const contentToClone = document.getElementById('dashboard-container'); const contentToExport = contentToClone.cloneNode(true); contentToExport.querySelectorAll('.pdf-hide').forEach(el => el.remove()); contentToExport.querySelectorAll('.tab-pane').forEach((pane, index) => { if (index !== 0) pane.remove(); }); contentToExport.querySelector('#tab-0-content').classList.remove('hidden'); document.body.appendChild(contentToExport); contentToExport.style.position = 'absolute'; contentToExport.style.left = '0'; contentToExport.style.top = '0'; contentToExport.style.width = '1024px'; contentToExport.style.zIndex = '-1'; contentToExport.style.backgroundColor = 'white'; contentToExport.style.padding = '2rem'; const canvas = await html2canvas(contentToExport, { scale: 2, useCORS: true }); document.body.removeChild(contentToExport); const imgData = canvas.toDataURL('image/png'); const imgWidth = canvas.width; const imgHeight = canvas.height; const pdf = new jsPDF({ orientation: 'p', unit: 'pt', format: 'a4' }); const pdfWidth = pdf.internal.pageSize.getWidth(); const scaledHeight = (imgHeight * pdfWidth) / imgWidth; const pageHeight = pdf.internal.pageSize.getHeight(); let heightLeft = scaledHeight; let position = 0; pdf.addImage(imgData, 'PNG', 0, position, pdfWidth, scaledHeight); heightLeft -= pageHeight; while (heightLeft > 0) { position = heightLeft - scaledHeight; pdf.addPage(); pdf.addImage(imgData, 'PNG', 0, position, pdfWidth, scaledHeight); heightLeft -= pageHeight; } pdf.save('Post-Production_Dashboard_Summary.pdf'); } catch (error) { console.error("Failed to generate PDF:", error); } finally { downloadBtn.disabled = false; downloadBtn.innerHTML = originalBtnContent; } } // --- UTILITY FUNCTIONS --- // function getProjectProgress(project) { if (project.tasks.length === 0) return 0; const completedTasks = project.tasks.filter(t => t.status === 'Completed').length; return Math.round((completedTasks / project.tasks.length) * 100); } // --- START THE APP --- // initialize(); });
Scroll to Top