tinyqc/public/js/charts.js
mahdahar ff90e0eb29 Initial commit: Add CodeIgniter 4 QC application with full MVC structure
- CodeIgniter 4 framework setup with SQL Server database config
- Models: Control, Test, Dept, Result, Daily/ Monthly entry models
- Controllers: Dashboard, Control, Test, Dept, Entry, Report, API endpoints
- Views: CRUD pages with modal dialogs, dashboard, reports
- Database: Migrations for control test and daily/monthly result tables
- Legacy v1 PHP application preserved in /v1 directory
- Documentation: AGENTS.md, VIEWS_RULES.md for development guidelines
2026-01-14 16:49:27 +07:00

129 lines
3.7 KiB
JavaScript

window.ChartManager = {
charts: {},
init(containerId, chartData, options = {}) {
const container = document.getElementById(containerId);
if (!container) return;
const ctx = container.getContext('2d');
if (this.charts[containerId]) {
this.charts[containerId].destroy();
}
const defaultOptions = {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
position: 'top',
}
}
};
this.charts[containerId] = new Chart(ctx, {
type: options.type || 'line',
data: chartData,
options: { ...defaultOptions, ...options }
});
return this.charts[containerId];
},
createTrendChart(containerId, labels, datasets) {
return this.init(containerId, {
labels,
datasets: datasets.map((ds, i) => ({
label: ds.label || `Control ${i + 1}`,
data: ds.data,
borderColor: ds.color || this.getColor(i),
backgroundColor: this.getColor(i, 0.1),
tension: 0.3,
fill: true,
pointRadius: 4,
pointHoverRadius: 6
}))
}, {
type: 'line',
plugins: {
title: {
display: true,
text: 'Monthly QC Trend'
}
}
});
},
createComparisonChart(containerId, labels, datasets) {
return this.init(containerId, {
labels,
datasets: datasets.map((ds, i) => ({
label: ds.label || `Control ${i + 1}`,
data: ds.data,
backgroundColor: this.getColor(i, 0.6),
borderColor: this.getColor(i),
borderWidth: 1
}))
}, {
type: 'bar',
plugins: {
title: {
display: true,
text: 'Control Comparison'
}
}
});
},
createViolationChart(containerId, labels, datasets) {
return this.init(containerId, {
labels,
datasets: datasets.map((ds, i) => ({
label: ds.label || `Control ${i + 1}`,
data: ds.data,
backgroundColor: ds.data.map(v => v > 100 ? 'rgba(239, 68, 68, 0.6)' : 'rgba(34, 197, 94, 0.6)'),
borderColor: ds.data.map(v => v > 100 ? 'rgb(239, 68, 68)' : 'rgb(34, 197, 94)'),
borderWidth: 1
}))
}, {
type: 'bar',
plugins: {
title: {
display: true,
text: 'QC Violations (Values > 100)'
}
}
});
},
getColor(index, alpha = 1) {
const colors = [
`rgba(59, 130, 246, ${alpha})`,
`rgba(16, 185, 129, ${alpha})`,
`rgba(245, 158, 11, ${alpha})`,
`rgba(239, 68, 68, ${alpha})`,
`rgba(139, 92, 246, ${alpha})`,
`rgba(236, 72, 153, ${alpha})`
];
return colors[index % colors.length];
},
destroy(containerId) {
if (this.charts[containerId]) {
this.charts[containerId].destroy();
delete this.charts[containerId];
}
},
destroyAll() {
Object.keys(this.charts).forEach(id => this.destroy(id));
}
};
document.addEventListener('DOMContentLoaded', () => {
const chartsContainer = document.getElementById('charts-container');
if (chartsContainer && typeof initReportCharts === 'function') {
initReportCharts();
}
});