Manufacturing Production Cost Tracker

Manufacturing Production Cost Tracker

Tracking and analyzing costs across production batches.

Production Batch Details

Batch ID Product Units Material Cost Labor Cost Overhead Cost Total Cost Cost/Unit

Overall Cost Composition

Cost Per Unit by Batch

$${metrics.totalCost.toLocaleString(undefined, {minimumFractionDigits: 2})}

Total Units Produced

${metrics.totalUnits.toLocaleString()}

Average Cost Per Unit

$${metrics.avgCostPerUnit.toLocaleString(undefined, {minimumFractionDigits: 2})}

Total Batches

${metrics.processedBatches.length}

`; // Render Table const tableBody = trackerPane.querySelector('#batch-table-body') || document.createElement('tbody'); tableBody.innerHTML = metrics.processedBatches.map(batch => ` ${batch.batchId} ${batch.productName} ${batch.unitsProduced.toLocaleString()} $${batch.materialCost.toLocaleString(undefined, {minimumFractionDigits: 2})} $${batch.laborCost.toLocaleString(undefined, {minimumFractionDigits: 2})} $${batch.overheadCost.toLocaleString(undefined, {minimumFractionDigits: 2})} $${batch.totalBatchCost.toLocaleString(undefined, {minimumFractionDigits: 2})} $${batch.costPerUnit.toLocaleString(undefined, {minimumFractionDigits: 2})} `).join(''); renderChartsForTab('tracker'); }; const renderConfigTab = () => { const configPane = document.getElementById('config-tab'); if(!configPane) return; configPane.innerHTML = `

Configure Production Data

Edit the JSON data for production batches below.

`; document.getElementById('data-config-input').value = JSON.stringify(costData, null, 2); document.getElementById('update-dashboard-btn').addEventListener('click', handleUpdateDashboard); }; // --- CHART RENDERING --- const renderChartsForTab = (tabId) => { if (tabId !== 'tracker') return; destroyCharts(); const metrics = processData(); chartInstances.doughnut = new Chart(document.getElementById('doughnut-chart').getContext('2d'), { type: 'doughnut', data: { labels: ['Total Material Cost', 'Total Labor Cost', 'Total Overhead Cost'], datasets: [{ data: [metrics.totalMaterial, metrics.totalLabor, metrics.totalOverhead], backgroundColor: ['#3b82f6', '#16a34a', '#f97316'] }] }, options: { responsive: true, maintainAspectRatio: true } }); chartInstances.line = new Chart(document.getElementById('line-chart').getContext('2d'), { type: 'line', data: { labels: metrics.processedBatches.map(b => b.batchId), datasets: [{ label: 'Cost Per Unit ($)', data: metrics.processedBatches.map(b => b.costPerUnit), borderColor: 'rgba(14, 165, 233, 1)', backgroundColor: 'rgba(56, 189, 248, 0.2)', fill: true, tension: 0.1 }] }, options: { responsive: true, maintainAspectRatio: true, scales: { y: { beginAtZero: true } } } }); }; // --- NAVIGATION & EVENT HANDLING --- const showTab = (tabIndex) => { currentTab = tabIndex; const tabId = tabs[tabIndex]; document.querySelectorAll('.tab-pane').forEach(pane => pane.classList.add('hidden')); document.getElementById(`${tabId}-tab`).classList.remove('hidden'); document.querySelectorAll('.tab-btn').forEach(btn => btn.classList.remove('active')); document.querySelector(`.tab-btn[data-tab='${tabId}']`).classList.add('active'); prevBtn.style.visibility = (currentTab === 0) ? 'hidden' : 'visible'; nextBtn.style.visibility = (currentTab >= tabs.length - 2) ? 'hidden' : 'visible'; downloadPdfBtn.style.visibility = (tabId === 'config') ? 'hidden' : 'visible'; if (tabId === 'tracker') { renderTrackerTab(); } }; tabNavigation.addEventListener('click', (e) => { if (e.target.matches('.tab-btn')) { const tabId = e.target.dataset.tab; const tabIndex = tabs.indexOf(tabId); showTab(tabIndex); } }); nextBtn.addEventListener('click', () => { if (currentTab < tabs.length - 1) showTab(currentTab + 1); }); prevBtn.addEventListener('click', () => { if (currentTab > 0) showTab(currentTab - 1); }); const handleUpdateDashboard = () => { const configInput = document.getElementById('data-config-input'); const errorDiv = document.getElementById('json-error'); const errorMessage = document.getElementById('json-error-message'); try { const newData = JSON.parse(configInput.value); costData = newData; errorDiv.classList.add('hidden'); renderTrackerTab(); alert('Dashboard updated successfully!'); showTab(0); } catch (error) { errorMessage.textContent = 'Invalid JSON format. ' + error.message; errorDiv.classList.remove('hidden'); } }; // --- PDF GENERATION --- downloadPdfBtn.addEventListener('click', () => { const { jsPDF } = window.jspdf; const pdfContainer = document.getElementById('pdf-content-container'); const activeTabElement = document.getElementById('tracker-tab'); if (!pdfContainer || !activeTabElement) return; const clone = activeTabElement.cloneNode(true); pdfContainer.innerHTML = ''; pdfContainer.appendChild(clone); html2canvas(pdfContainer, { scale: 2, useCORS: true, logging: false, width: pdfContainer.scrollWidth, height: pdfContainer.scrollHeight }) .then(canvas => { const imgData = canvas.toDataURL('image/png'); const pdf = new jsPDF({ orientation: 'landscape', unit: 'pt', format: 'a4' }); const pdfWidth = pdf.internal.pageSize.getWidth(); const pdfHeight = pdf.internal.pageSize.getHeight(); const imgWidth = canvas.width; const imgHeight = canvas.height; const ratio = imgWidth / imgHeight; let finalImgHeight = pdfWidth / ratio; let heightLeft = finalImgHeight; let position = 0; pdf.text(`Manufacturing Production Cost Report`, 40, 40); pdf.addImage(imgData, 'PNG', 0, 60, pdfWidth, finalImgHeight); heightLeft -= (pdfHeight - 60); while (heightLeft > 0) { position = heightLeft - finalImgHeight; pdf.addPage(); pdf.addImage(imgData, 'PNG', 0, position, pdfWidth, finalImgHeight); heightLeft -= pdfHeight; } pdf.save(`Production_Cost_Tracker_Report.pdf`); pdfContainer.innerHTML = ''; }).catch(err => { console.error("PDF generation failed:", err); alert("Sorry, there was an error creating the PDF."); }); }); // --- INITIALIZATION --- createTabs(); renderAllTabs(); showTab(0); });
Scroll to Top