feat(110): statistics summary
Phase 110 complete: - add Statistics -> Podsumowanie page - add monthly order count and value charts per integration plus total - use Chart.js with table fallback and 04-2026 default history start - update PAUL and DOCS technical documentation
This commit is contained in:
File diff suppressed because one or more lines are too long
119
public/assets/js/modules/statistics-summary-charts.js
Normal file
119
public/assets/js/modules/statistics-summary-charts.js
Normal file
@@ -0,0 +1,119 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var palette = ['#2563eb', '#0f766e', '#c2410c', '#7c3aed', '#be123c', '#0369a1', '#4d7c0f', '#9333ea'];
|
||||
var totalColor = '#111827';
|
||||
|
||||
function parseData() {
|
||||
var node = document.getElementById('js-statistics-summary-data');
|
||||
if (!node) return null;
|
||||
|
||||
try {
|
||||
return JSON.parse(node.textContent || '{}');
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function colorForSeries(item, index) {
|
||||
return item.key === 'total' ? totalColor : palette[index % palette.length];
|
||||
}
|
||||
|
||||
function moneyLabel(value) {
|
||||
return Number(value || 0).toLocaleString('pl-PL', {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2
|
||||
});
|
||||
}
|
||||
|
||||
function datasetForSeries(item, index) {
|
||||
var color = colorForSeries(item, index);
|
||||
var isTotal = item.key === 'total';
|
||||
|
||||
return {
|
||||
label: item.label || item.key || '',
|
||||
data: item.values || [],
|
||||
borderColor: color,
|
||||
backgroundColor: color,
|
||||
borderWidth: isTotal ? 3 : 2,
|
||||
pointRadius: isTotal ? 4 : 3,
|
||||
pointHoverRadius: isTotal ? 6 : 5,
|
||||
tension: 0.25
|
||||
};
|
||||
}
|
||||
|
||||
function renderChart(container, chart) {
|
||||
if (!window.Chart || !container || !chart || !Array.isArray(chart.labels) || !Array.isArray(chart.series)) return;
|
||||
|
||||
var canvas = container.querySelector('canvas');
|
||||
if (!canvas) return;
|
||||
|
||||
var isMoney = chart.valueType === 'money';
|
||||
var context = canvas.getContext('2d');
|
||||
|
||||
new window.Chart(context, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: chart.labels,
|
||||
datasets: chart.series.map(datasetForSeries)
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
interaction: {
|
||||
mode: 'index',
|
||||
intersect: false
|
||||
},
|
||||
plugins: {
|
||||
legend: {
|
||||
position: 'bottom',
|
||||
labels: {
|
||||
boxWidth: 18,
|
||||
boxHeight: 3,
|
||||
usePointStyle: false
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
callbacks: {
|
||||
label: function (item) {
|
||||
var label = item.dataset.label ? item.dataset.label + ': ' : '';
|
||||
return label + (isMoney ? moneyLabel(item.parsed.y) : Math.round(item.parsed.y));
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
scales: {
|
||||
x: {
|
||||
grid: {
|
||||
display: false
|
||||
}
|
||||
},
|
||||
y: {
|
||||
beginAtZero: true,
|
||||
ticks: {
|
||||
callback: function (value) {
|
||||
return isMoney ? moneyLabel(value) : value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function init() {
|
||||
var data = parseData();
|
||||
if (!data) return;
|
||||
|
||||
document.querySelectorAll('[data-statistics-chart]').forEach(function (container) {
|
||||
var key = container.getAttribute('data-statistics-chart');
|
||||
renderChart(container, data[key]);
|
||||
});
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', init);
|
||||
} else {
|
||||
init();
|
||||
}
|
||||
})();
|
||||
Reference in New Issue
Block a user