Defect Rate
${defectRate}%
`;
container.innerHTML += card;
});
};
// --- CHARTING LOGIC ---
const createOrUpdateChart = (ctx, type, data, options) => {
if (!ctx) return;
const chartId = ctx.id;
if (chartInstances[chartId]) chartInstances[chartId].destroy();
chartInstances[chartId] = new Chart(ctx, { type, data, options });
};
const renderCharts = () => {
// Output by Line Chart
createOrUpdateChart(document.getElementById('outputByLineChart'), 'bar', {
labels: productionLines.map(p => p.name),
datasets: [{ label: 'Units Produced', data: productionLines.map(p => p.output), backgroundColor: '#3b82f6' }]
}, { responsive: true, maintainAspectRatio: false, plugins: { legend: { display: false } } });
// Machine Status Chart
const statusCounts = productionLines.reduce((acc, p) => { acc[p.status] = (acc[p.status] || 0) + 1; return acc; }, {});
createOrUpdateChart(document.getElementById('machineStatusChart'), 'doughnut', {
labels: Object.keys(statusCounts),
datasets: [{ data: Object.values(statusCounts), backgroundColor: ['#22c55e', '#f59e0b', '#ef4444'] }]
}, { responsive: true, maintainAspectRatio: false });
// OEE Trend Chart
const today = new Date();
const labels = Array.from({length: 7}, (_, i) => {
const d = new Date();
d.setDate(today.getDate() - (6 - i));
return d;
});
const datasets = productionLines.map((line, index) => {
const colors = ['#3b82f6', '#8b5cf6', '#ef4444', '#10b981', '#f59e0b'];
return {
label: line.name,
data: line.oeeHistory,
borderColor: colors[index % colors.length],
tension: 0.3,
fill: false
}
});
createOrUpdateChart(document.getElementById('oeeTrendChart'), 'line', {
labels: labels,
datasets: datasets
}, { responsive: true, maintainAspectRatio: false, scales: { x: { type: 'time', time: { unit: 'day' } } } });
};
// --- FORM HANDLING ---
const populateLineSelect = () => {
if (!lineSelect) return;
lineSelect.innerHTML = productionLines.map(p => `
`).join('');
updateFormForSelectedLine();
};
const updateFormForSelectedLine = () => {
const selectedId = lineSelect.value;
const line = productionLines.find(p => p.id === selectedId);
if (line) {
document.getElementById('line-id-input').value = line.id;
document.getElementById('line-status').value = line.status;
document.getElementById('line-output').value = line.output;
document.getElementById('line-defects').value = line.defects;
document.getElementById('line-oee').value = line.oee;
}
};
lineSelect.addEventListener('change', updateFormForSelectedLine);
productionForm.addEventListener('submit', (e) => {
e.preventDefault();
const id = document.getElementById('line-id-input').value;
const index = productionLines.findIndex(p => p.id === id);
if (index !== -1) {
productionLines[index].status = document.getElementById('line-status').value;
productionLines[index].output = parseInt(document.getElementById('line-output').value);
productionLines[index].defects = parseInt(document.getElementById('line-defects').value);
productionLines[index].oee = parseInt(document.getElementById('line-oee').value);
// Also update last point in history for the trend chart
const history = productionLines[index].oeeHistory;
history[history.length - 1] = productionLines[index].oee;
}
renderAll();
alert('Production line data updated successfully.');
});
resetDataBtn.addEventListener('click', () => { if (confirm('Reset all data to sample data?')) init(); });
// --- PDF DOWNLOAD ---
downloadPdfBtn.addEventListener('click', () => {
const { jsPDF } = window.jspdf;
const content = document.getElementById('dashboard-content-to-print');
html2canvas(content, { scale: 2, useCORS: true, backgroundColor: '#ffffff' }).then(canvas => {
const imgData = canvas.toDataURL('image/png');
const pdf = new jsPDF({ orientation: 'p', unit: 'mm', format: 'a4' });
const imgProps = pdf.getImageProperties(imgData);
const pdfWidth = pdf.internal.pageSize.getWidth();
const pdfHeight = (imgProps.height * pdfWidth) / imgProps.width;
pdf.addImage(imgData, 'PNG', 0, 0, pdfWidth, pdfHeight);
pdf.save('Manufacturing_Dashboard_Report.pdf');
});
});
// --- INITIALIZATION ---
const init = () => {
generateSampleData();
renderAll();
updateNavButtons();
};
init();
});