| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237 |
- {{-- resources/views/livewire/dynamic_report.blade.php --}}
- <div id="card--dashboard">
- <div>
- <div class="chart-row mb-3">
- <div class="chart-card">
- <div class="chart-body" style="padding-block: 20px">
- <div class="row row-gap-3">
- <div class="col-4">
- <div wire:ignore>
- <label for="filter-courses">Corso</label>
- <select id="filter-courses" multiple class="form-select">
- @foreach ($filter_options['courses'] as $course)
- <option value="{{ $course }}">{{ $course }}</option>
- @endforeach
- </select>
- </div>
- </div>
- <div class="col-4">
- <div wire:ignore>
- <label for="filter-levels">Livello</label>
- <select id="filter-levels" multiple class="form-select">
- @foreach ($filter_options['levels'] as $level)
- <option value="{{ $level['id'] }}">{{ $level['name'] }}</option>
- @endforeach
- </select>
- </div>
- </div>
- <div class="col-4">
- <div wire:ignore>
- <label for="filter-types">Tipo</label>
- <select id="filter-types" multiple class="form-select">
- @foreach ($filter_options['types'] as $type)
- <option value="{{ $type['id'] }}">{{ $type['name'] }}</option>
- @endforeach
- </select>
- </div>
- </div>
- <div class="col-4">
- <div wire:ignore>
- <label for="filter-seasons">Stagione</label>
- <select id="filter-seasons" multiple class="form-select">
- @foreach ($filter_options['seasons'] as $season)
- <option value="{{ $season }}">{{ $season }}</option>
- @endforeach
- </select>
- </div>
- </div>
- <div class="col-4">
- <div wire:ignore>
- <label for="filter-months">Mesi</label>
- <select id="filter-months" multiple class="form-select">
- @foreach ($filter_options['months'] as $month)
- <option value="{{ $month['id'] }}">{{ $month['name'] }}</option>
- @endforeach
- </select>
- </div>
- </div>
- <div class="col text-end mt-4">
- <button type="button" class="btn--ui" onclick="applyFilters()">
- Applica filtri
- </button>
- </div>
- </div>
- </div>
- </div>
- </div>
- <div class="chart-row mb-0">
- <div class="chart-card">
- <div class="chart-body" wire:ignore>
- <div class="chart-wrapper" style="height: calc(100dvh - 450px)">
- <div class="missing-filter-warning" id="filter_msg" wire:ignore>
- <div class="chart-placeholder">
- <div style="text-align: center;">
- <div style="font-size: 3rem; margin-bottom: 1rem; opacity: 0.3;">📊</div>
- <p style="font-size: 1.25rem; font-weight: 600; margin: 0;">Seleziona uno o più criteri per visualizzare il report</p>
- </div>
- </div>
- </div>
- <canvas id="dynamicReportChart"></canvas>
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- @push('css')
- <link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet" />
- <link rel="stylesheet" href="/css/chart-reports.css">
- <style>
- .select2-container--default .select2-selection--multiple {
- min-height: 40px !important;
- }
- .select2-container--default .select2-search--inline .select2-search__field {
- margin-top: 0;
- }
- .select2-container--default .select2-search--inline {
- display: inline-block;
- padding-top: 0;
- height: 26px !important;
- }
- </style>
- @endpush
- @push('scripts')
- <script src="https://code.jquery.com/jquery-2.2.4.min.js" integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44=" crossorigin="anonymous"></script>
- <script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
- <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
- @endpush
- @push('scripts')
- <script>
- document.addEventListener("livewire:load", function () {
- function initSelect2() {
- const select2Options = {
- language: {
- noResults: function () {
- return "Nessun risultato";
- },
- },
- };
- const $courses = $("#filter-courses").select2(select2Options);
- $courses.off('change.dynamicReport').on('change.dynamicReport', function () {
- @this.set("filters.courses", $(this).val() ?? []);
- });
- const $levels = $("#filter-levels").select2(select2Options);
- $levels.off('change.dynamicReport').on('change.dynamicReport', function () {
- @this.set("filters.levels", $(this).val() ?? []);
- });
- const $types = $("#filter-types").select2(select2Options);
- $types.off('change.dynamicReport').on('change.dynamicReport', function () {
- @this.set("filters.types", $(this).val() ?? []);
- });
- const $seasons = $("#filter-seasons").select2(select2Options);
- $seasons.off('change.dynamicReport').on('change.dynamicReport', function () {
- @this.set("filters.seasons", $(this).val() ?? []);
- });
- const $months = $("#filter-months").select2(select2Options);
- $months.off('change.dynamicReport').on('change.dynamicReport', function () {
- @this.set("filters.months", $(this).val() ?? []);
- });
- }
- initSelect2();
- });
- </script>
- @endpush
- @push('scripts')
- <script>
- let dynamicReportChart = null;
- function buildOrUpdateChart(payload) {
- const ctx = document.getElementById('dynamicReportChart');
- if (!ctx) return;
- let data = payload.chart ?? { labels: [], datasets: [] };
- data = applyDatasetStyles(data);
- if (dynamicReportChart) {
- dynamicReportChart.data.labels = data.labels;
- dynamicReportChart.data.datasets = data.datasets;
- dynamicReportChart.update();
- return;
- }
- dynamicReportChart = new Chart(ctx, {
- type: 'bar',
- data: data,
- options: {
- responsive: true,
- maintainAspectRatio: false,
- interaction: {
- mode: 'index',
- intersect: false,
- },
- plugins: {
- tooltip: {
- mode: 'index',
- intersect: false,
- itemSort: (a, b) => b.raw - a.raw,
- },
- legend: { display: true, position: 'bottom' },
- },
- scales: {
- y: { beginAtZero: true }
- }
- }
- });
- }
- function applyDatasetStyles(data) {
- if (!data?.datasets) return data;
- data.datasets = data.datasets.map((ds, i) => {
- const hue = (i * 47) % 360;
- return {
- ...ds,
- barThickness: 10,
- maxBarThickness: 10,
- backgroundColor: `hsla(${hue}, 70%, 55%, 0.85)`,
- borderColor: `hsl(${hue}, 70%, 45%)`,
- borderWidth: 0,
- };
- });
- return data;
- }
- function applyFilters() {
- let filter_msg = document.getElementById("filter_msg");
- if (filter_msg) filter_msg.style.display = "none";
- @this.applyFilters();
- }
- window.addEventListener('dynamic-report:updated', (e) => {
- buildOrUpdateChart(e.detail);
- });
- </script>
- @endpush
|