Files
nrml_dashboard/dashboard/public/js/dashboard/charts.js
2026-03-19 09:20:42 +07:00

365 lines
10 KiB
JavaScript

Chart.register(ChartDataLabels);
const charts = {};
function buildStackedChart(canvasId, labels, datasets) {
const ctx = document.getElementById(canvasId);
if (!ctx) return;
if (charts[canvasId]) {
charts[canvasId].destroy();
}
charts[canvasId] = new Chart(ctx, {
type: "bar",
data: {
labels: labels,
datasets: datasets,
datalabels: {
display: true
}
},
plugins: [ChartDataLabels],
options: {
responsive: true,
maintainAspectRatio: false,
layout: {
padding: {
top: 20,
bottom: 30
}
},
plugins: {
legend: {
position: 'bottom',
align: 'center',
labels: {
padding: 20,
boxWidth: 10,
boxHeight: 10,
usePointStyle: true,
pointStyle: 'circle'
}
},
datalabels: {
color: "#000",
anchor: "end",
align: "top",
clamp: true,
clip: false,
font: {
weight: "bold",
size: 10
},
formatter: function (value) {
return value > 0 ? value : null;
}
}
},
scales: {
x: {
stacked: true
},
y: {
stacked: true,
beginAtZero: true
}
}
}
});
}
function buildChart(id, type, labels, data) {
const ctx = document.getElementById(id);
if (!ctx) return;
if (charts[id]) charts[id].destroy();
charts[id] = new Chart(ctx, {
type: type,
data: {
labels: labels,
datasets: [{
data: data,
borderWidth: 2,
tension: 0.3,
barPercentage: 0.8,
categoryPercentage: 0.6,
maxBarThickness: 50
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
layout: {
padding: {
top: 30,
bottom: 30
}
},
plugins: {
legend: {
position: 'bottom',
align: 'center',
display: type === 'pie' || type === 'doughnut',
labels: {
padding: 10,
boxWidth: 14,
boxHeight: 14,
usePointStyle: true,
pointStyle: 'circle'
}
},
datalabels: {
color: "#282626",
anchor: type === "bar" ? "end" : "center",
align: type === "bar" ? "top" : "center",
font: {
size: 10
},
formatter: function(value, ctx) {
const data = ctx.chart.data.datasets[0].data;
const total = data.reduce((a, b) => a + b, 0);
const percent = total ? (value / total * 100).toFixed(1) : 0;
return percent + '%';
}
}
}
}
});
}
function buildMixedTrendChart(canvasId, labels, samples, fluRate, covidRate) {
const ctx = document.getElementById(canvasId);
if (!ctx) return;
if (charts[canvasId]) charts[canvasId].destroy();
charts[canvasId] = new Chart(ctx, {
data: {
labels: labels,
datasets: [
{
type: 'line',
label: 'Influenza %',
data: fluRate,
borderColor: '#fa2929',
backgroundColor: '#fa2929',
tension: 0.4,
yAxisID: 'y1',
pointStyle: 'line',
},
{
type: 'line',
label: 'COVID-19 %',
data: covidRate,
borderColor: '#1976D2',
backgroundColor: '#1976D2',
tension: 0.4,
yAxisID: 'y1',
pointStyle: 'line',
},
{
type: 'bar',
label: 'Total Cases',
data: samples,
backgroundColor: '#0B8F3C',
borderRadius: 2,
barPercentage: 0.8,
categoryPercentage: 0.7,
yAxisID: 'y',
}
]
},
plugins: [ChartDataLabels],
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
position: 'bottom',
labels: {
usePointStyle: true,
padding: 20
}
},
datalabels: {
align: "top",
anchor: "end",
color: "#555",
font: {
size: 10
},
formatter: function (value, context) {
if (Number(value) === 0) return null;
if (context.dataset.type === 'line') {
return value + '%';
}
return value;
}
}
},
layout: {
padding: {
top: 30,
bottom: 20
}
},
scales: {
y: {
position: 'left',
title: {
display: true,
text: 'Cases'
}
},
y1: {
position: 'right',
grid: { drawOnChartArea: false },
title: {
display: true,
text: '% Positivity'
},
}
}
}
});
}
// function buildMixedTrendChart(canvasId, labels, samples, positivity) {
// const ctx = document.getElementById(canvasId);
// if (!ctx) return;
// if (charts[canvasId]) charts[canvasId].destroy();
// charts[canvasId] = new Chart(ctx, {
// data: {
// labels: labels,
// datasets: [
// {
// type: 'line',
// label: '% Positive',
// data: positivity,
// borderColor: '#1e6ef2',
// borderWidth: 2,
// tension: 0.4,
// fill: false,
// pointRadius: 2,
// pointStyle: 'line',
// yAxisID: 'y1',
// },
// {
// type: 'bar',
// label: 'Total sample ',
// data: samples,
// backgroundColor: '#2ecc71',
// borderRadius: 2,
// barPercentage: 0.8,
// categoryPercentage: 0.7,
// yAxisID: 'y',
// }
// ]
// },
// plugins: [ChartDataLabels],
// options: {
// responsive: true,
// maintainAspectRatio: false,
// plugins: {
// legend: {
// position: 'bottom',
// align: 'center',
// labels: {
// usePointStyle: true,
// padding: 20,
// boxWidth: 30,
// font: { size: 12 }
// }
// },
// datalabels: {
// align: "top",
// anchor: "end",
// color: "#555",
// font: {
// size: 10
// },
// formatter: function (value, context) {
// if (Number(value) === 0) return null;
// if (context.dataset.type === 'line') {
// console.log(value);
// return value + '%';
// }
// return value;
// }
// }
// },
// layout: {
// padding: {
// top: 20,
// bottom: 50
// }
// },
// scales: {
// y: {
// position: 'left',
// title: {
// display: true,
// text: 'Total sample'
// }
// },
// y1: {
// position: 'right',
// grid: {
// drawOnChartArea: false
// },
// title: {
// display: true,
// text: '% Positive'
// },
// ticks: {
// callback: value => value + '%'
// }
// }
// }
// }
// });
// }