working on detail page for sari, lil, amd lbm
This commit is contained in:
108
dashboard/public/js/dashboard/charts.js
Normal file
108
dashboard/public/js/dashboard/charts.js
Normal file
@@ -0,0 +1,108 @@
|
||||
const charts = {};
|
||||
|
||||
function buildChart(id, type, labels, data, label = 'Cases') {
|
||||
|
||||
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: [{
|
||||
label: label,
|
||||
data: data,
|
||||
borderWidth: 2,
|
||||
tension: 0.3
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
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: 4,
|
||||
pointStyle: 'line',
|
||||
yAxisID: 'y1'
|
||||
},
|
||||
{
|
||||
type: 'bar',
|
||||
label: 'Total sample',
|
||||
data: samples,
|
||||
backgroundColor: '#2ecc71',
|
||||
borderRadius: 6,
|
||||
barPercentage: 0.6,
|
||||
pointStyle: 'rect',
|
||||
categoryPercentage: 0.7,
|
||||
yAxisID: 'y',
|
||||
},
|
||||
]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
plugins: {
|
||||
legend: {
|
||||
position: 'bottom',
|
||||
align: 'center',
|
||||
labels: {
|
||||
usePointStyle: true,
|
||||
padding: 20,
|
||||
boxWidth: 30,
|
||||
font: {
|
||||
size: 12
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
layout: {
|
||||
padding: {
|
||||
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 + '%'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
132
dashboard/public/js/dashboard/filter.js
Normal file
132
dashboard/public/js/dashboard/filter.js
Normal file
@@ -0,0 +1,132 @@
|
||||
class DashboardFilter {
|
||||
|
||||
constructor(onChange) {
|
||||
|
||||
this.onChange = onChange;
|
||||
|
||||
this.rangeSelect = document.getElementById("trend_range");
|
||||
this.startYear = document.getElementById("start_year");
|
||||
this.startWeek = document.getElementById("start_week");
|
||||
this.endYear = document.getElementById("end_year");
|
||||
this.endWeek = document.getElementById("end_week");
|
||||
this.customContainer = document.getElementById("custom_range_container");
|
||||
|
||||
if (!this.rangeSelect) return;
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
||||
init() {
|
||||
|
||||
this.populateFilters();
|
||||
|
||||
this.rangeSelect.addEventListener("change", () => {
|
||||
|
||||
const val = this.rangeSelect.value;
|
||||
|
||||
if (val === "custom") {
|
||||
this.customContainer.style.display = "flex";
|
||||
return;
|
||||
}
|
||||
|
||||
this.customContainer.style.display = "none";
|
||||
|
||||
const range = this.lastWeeks(parseInt(val));
|
||||
|
||||
this.apply(range);
|
||||
this.trigger();
|
||||
|
||||
});
|
||||
|
||||
["start_year","start_week","end_year","end_week"].forEach(id => {
|
||||
|
||||
const el = document.getElementById(id);
|
||||
|
||||
if (el) el.addEventListener("change", ()=>this.trigger());
|
||||
|
||||
});
|
||||
|
||||
const defaultRange = this.lastWeeks(8);
|
||||
|
||||
this.apply(defaultRange);
|
||||
this.trigger();
|
||||
}
|
||||
|
||||
trigger() {
|
||||
|
||||
this.onChange(
|
||||
this.startYear.value,
|
||||
this.startWeek.value,
|
||||
this.endYear.value,
|
||||
this.endWeek.value
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
apply(range) {
|
||||
|
||||
this.startYear.value = range.startYear;
|
||||
this.startWeek.value = range.startWeek;
|
||||
this.endYear.value = range.endYear;
|
||||
this.endWeek.value = range.endWeek;
|
||||
|
||||
}
|
||||
|
||||
populateFilters() {
|
||||
|
||||
const year = new Date().getFullYear();
|
||||
|
||||
for (let y = year-10; y <= year; y++) {
|
||||
|
||||
this.startYear.innerHTML += `<option value="${y}">${y}</option>`;
|
||||
this.endYear.innerHTML += `<option value="${y}">${y}</option>`;
|
||||
|
||||
}
|
||||
|
||||
for (let w = 1; w <= 53; w++) {
|
||||
|
||||
this.startWeek.innerHTML += `<option value="${w}">W${w}</option>`;
|
||||
this.endWeek.innerHTML += `<option value="${w}">W${w}</option>`;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
getISOWeek(date) {
|
||||
|
||||
const d = new Date(Date.UTC(date.getFullYear(),date.getMonth(),date.getDate()));
|
||||
|
||||
d.setUTCDate(d.getUTCDate()+4-(d.getUTCDay()||7));
|
||||
|
||||
const yearStart = new Date(Date.UTC(d.getUTCFullYear(),0,1));
|
||||
|
||||
const week = Math.ceil((((d-yearStart)/86400000)+1)/7);
|
||||
|
||||
return {year:d.getUTCFullYear(),week};
|
||||
|
||||
}
|
||||
|
||||
lastWeeks(n) {
|
||||
|
||||
const end = this.getISOWeek(new Date());
|
||||
|
||||
let startWeek = end.week-n+1;
|
||||
let startYear = end.year;
|
||||
|
||||
while(startWeek<=0){
|
||||
|
||||
startWeek += 52;
|
||||
startYear--;
|
||||
|
||||
}
|
||||
|
||||
return {
|
||||
startYear,
|
||||
startWeek,
|
||||
endYear:end.year,
|
||||
endWeek:end.week
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user