111 lines
4.1 KiB
PHP
111 lines
4.1 KiB
PHP
@php
|
|
$chartId = 'aboChart_' . str_replace('.', '', microtime(true));
|
|
$chartDataJson = json_encode(array_values($chartData));
|
|
$chartLabelsJson = json_encode(array_values($chartMonths));
|
|
$nonNullValues = array_filter($chartData, fn($v) => $v !== null);
|
|
$maxVal = count($nonNullValues) ? max($nonNullValues) : 0;
|
|
|
|
// Großzügige Schritte für die Y-Achse
|
|
if ($maxVal <= 5) { $stepSize = 1; }
|
|
elseif ($maxVal <= 10) { $stepSize = 2; }
|
|
elseif ($maxVal <= 20) { $stepSize = 5; }
|
|
elseif ($maxVal <= 50) { $stepSize = 10; }
|
|
elseif ($maxVal <= 100) { $stepSize = 20; }
|
|
elseif ($maxVal <= 200) { $stepSize = 50; }
|
|
elseif ($maxVal <= 500) { $stepSize = 100; }
|
|
elseif ($maxVal <= 1000) { $stepSize = 200; }
|
|
else { $stepSize = 500; }
|
|
|
|
// Genug Platz nach oben, damit das Label nicht abgeschnitten wird
|
|
$suggestedMax = $maxVal + $stepSize;
|
|
@endphp
|
|
|
|
<div class="card mb-4">
|
|
<div class="card-body pb-2">
|
|
<div class="d-flex justify-content-between align-items-center flex-wrap">
|
|
<h6 class="font-weight-bold mb-2">
|
|
{{ __('abo.chart_monthly_abos') }}
|
|
<span class="text-muted font-weight-normal ml-1">{{ $chartYear }}</span>
|
|
</h6>
|
|
<div class="mb-2">
|
|
@foreach($chartYears as $y)
|
|
<a href="{{ url()->current() }}?year={{ $y }}"
|
|
class="btn btn-xs btn-sm {{ $chartYear == $y ? 'btn-secondary' : 'btn-outline-secondary' }} mr-1 mb-1">
|
|
{{ $y }}
|
|
</a>
|
|
@endforeach
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<hr class="m-0">
|
|
<div class="card-body pt-3 pb-2">
|
|
<canvas id="{{ $chartId }}" height="80"></canvas>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="/vendor/libs/chartjs/chartjs.js"></script>
|
|
<script>
|
|
(function () {
|
|
// Inline data-labels plugin für Chart.js v2
|
|
var dataLabelsPlugin = {
|
|
afterDatasetsDraw: function (chart) {
|
|
var ctx = chart.ctx;
|
|
chart.data.datasets.forEach(function (dataset, i) {
|
|
var meta = chart.getDatasetMeta(i);
|
|
if (meta.hidden) { return; }
|
|
meta.data.forEach(function (bar, index) {
|
|
var value = dataset.data[index];
|
|
if (value === null || value === undefined || value === 0) { return; }
|
|
ctx.save();
|
|
ctx.fillStyle = '#495057';
|
|
ctx.font = 'bold 11px -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif';
|
|
ctx.textAlign = 'center';
|
|
ctx.textBaseline = 'bottom';
|
|
ctx.fillText(value, bar._model.x, bar._model.y - 3);
|
|
ctx.restore();
|
|
});
|
|
});
|
|
}
|
|
};
|
|
|
|
var ctx = document.getElementById('{{ $chartId }}').getContext('2d');
|
|
new Chart(ctx, {
|
|
type: 'bar',
|
|
plugins: [dataLabelsPlugin],
|
|
data: {
|
|
labels: {!! $chartLabelsJson !!},
|
|
datasets: [{
|
|
label: '{{ __('abo.chart_active_abos') }}',
|
|
data: {!! $chartDataJson !!},
|
|
backgroundColor: 'rgba(102, 110, 232, 0.2)',
|
|
borderColor: 'rgba(102, 110, 232, 0.8)',
|
|
borderWidth: 1
|
|
}]
|
|
},
|
|
options: {
|
|
responsive: true,
|
|
legend: { display: false },
|
|
tooltips: { enabled: false },
|
|
layout: {
|
|
padding: { top: 20 }
|
|
},
|
|
scales: {
|
|
yAxes: [{
|
|
ticks: {
|
|
beginAtZero: true,
|
|
stepSize: {{ $stepSize }},
|
|
suggestedMax: {{ $suggestedMax }},
|
|
callback: function (value) {
|
|
return Number.isInteger(value) ? value : null;
|
|
}
|
|
},
|
|
gridLines: { color: 'rgba(0,0,0,0.05)' }
|
|
}],
|
|
xAxes: [{
|
|
gridLines: { display: false }
|
|
}]
|
|
}
|
|
}
|
|
});
|
|
}());
|
|
</script>
|