dynamic_report.blade.php 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. {{-- resources/views/livewire/dynamic_report.blade.php --}}
  2. <div id="card--dashboard">
  3. <div>
  4. <div class="row" id="filter_msg" wire:ignore>
  5. <div class="col-12">
  6. <div class="alert alert-info">Seleziona uno o più criteri per visualizzare il report</div>
  7. </div>
  8. </div>
  9. <div class="chart-row">
  10. <div class="chart-card">
  11. <div class="chart-body" style="padding-block: 20px">
  12. <div class="row row-gap-3">
  13. <div class="col-4">
  14. <div wire:ignore>
  15. <label for="filter-courses">Corso</label>
  16. <select id="filter-courses" multiple class="form-select">
  17. @foreach ($filter_options['courses'] as $course)
  18. <option value="{{ $course }}">{{ $course }}</option>
  19. @endforeach
  20. </select>
  21. </div>
  22. </div>
  23. <div class="col-4">
  24. <div wire:ignore>
  25. <label for="filter-levels">Livello</label>
  26. <select id="filter-levels" multiple class="form-select">
  27. @foreach ($filter_options['levels'] as $level)
  28. <option value="{{ $level['id'] }}">{{ $level['name'] }}</option>
  29. @endforeach
  30. </select>
  31. </div>
  32. </div>
  33. <div class="col-4">
  34. <div wire:ignore>
  35. <label for="filter-types">Tipo</label>
  36. <select id="filter-types" multiple class="form-select">
  37. @foreach ($filter_options['types'] as $type)
  38. <option value="{{ $type['id'] }}">{{ $type['name'] }}</option>
  39. @endforeach
  40. </select>
  41. </div>
  42. </div>
  43. <div class="col-4">
  44. <div wire:ignore>
  45. <label for="filter-seasons">Stagione</label>
  46. <select id="filter-seasons" multiple class="form-select">
  47. @foreach ($filter_options['seasons'] as $season)
  48. <option value="{{ $season }}">{{ $season }}</option>
  49. @endforeach
  50. </select>
  51. </div>
  52. </div>
  53. <div class="col-4">
  54. <div wire:ignore>
  55. <label for="filter-months">Mesi</label>
  56. <select id="filter-months" multiple class="form-select">
  57. @foreach ($filter_options['months'] as $month)
  58. <option value="{{ $month['id'] }}">{{ $month['name'] }}</option>
  59. @endforeach
  60. </select>
  61. </div>
  62. </div>
  63. <div class="col text-end mt-4">
  64. <button type="button" class="btn--ui" onclick="applyFilters()">
  65. Applica filtri
  66. </button>
  67. </div>
  68. </div>
  69. </div>
  70. </div>
  71. </div>
  72. <div class="chart-row mb-0">
  73. <div class="chart-card">
  74. <div class="chart-body" wire:ignore>
  75. <div class="chart-wrapper" style="height: 600px">
  76. <canvas id="dynamicReportChart"></canvas>
  77. </div>
  78. </div>
  79. </div>
  80. </div>
  81. </div>
  82. </div>
  83. @push('css')
  84. <link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet" />
  85. <link rel="stylesheet" href="/css/chart-reports.css">
  86. <style>
  87. .select2-container--default .select2-selection--multiple {
  88. min-height: 40px !important;
  89. }
  90. .select2-container--default .select2-search--inline .select2-search__field {
  91. margin-top: 0;
  92. }
  93. .select2-container--default .select2-search--inline {
  94. display: inline-block;
  95. padding-top: 0;
  96. height: 26px !important;
  97. }
  98. </style>
  99. @endpush
  100. @push('scripts')
  101. <script src="https://code.jquery.com/jquery-2.2.4.min.js" integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44=" crossorigin="anonymous"></script>
  102. <script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
  103. <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
  104. @endpush
  105. @push('scripts')
  106. <script>
  107. document.addEventListener("livewire:load", function () {
  108. function initSelect2() {
  109. const select2Options = {
  110. language: {
  111. noResults: function () {
  112. return "Nessun risultato";
  113. },
  114. },
  115. };
  116. const $courses = $("#filter-courses").select2(select2Options);
  117. $courses.off('change.dynamicReport').on('change.dynamicReport', function () {
  118. @this.set("filters.courses", $(this).val() ?? []);
  119. });
  120. const $levels = $("#filter-levels").select2(select2Options);
  121. $levels.off('change.dynamicReport').on('change.dynamicReport', function () {
  122. @this.set("filters.levels", $(this).val() ?? []);
  123. });
  124. const $types = $("#filter-types").select2(select2Options);
  125. $types.off('change.dynamicReport').on('change.dynamicReport', function () {
  126. @this.set("filters.types", $(this).val() ?? []);
  127. });
  128. const $seasons = $("#filter-seasons").select2(select2Options);
  129. $seasons.off('change.dynamicReport').on('change.dynamicReport', function () {
  130. @this.set("filters.seasons", $(this).val() ?? []);
  131. });
  132. const $months = $("#filter-months").select2(select2Options);
  133. $months.off('change.dynamicReport').on('change.dynamicReport', function () {
  134. @this.set("filters.months", $(this).val() ?? []);
  135. });
  136. }
  137. initSelect2();
  138. });
  139. </script>
  140. @endpush
  141. @push('scripts')
  142. <script>
  143. let dynamicReportChart = null;
  144. function buildOrUpdateChart(payload) {
  145. const ctx = document.getElementById('dynamicReportChart');
  146. if (!ctx) return;
  147. let data = payload.chart ?? { labels: [], datasets: [] };
  148. data = applyDatasetStyles(data);
  149. if (dynamicReportChart) {
  150. dynamicReportChart.data.labels = data.labels;
  151. dynamicReportChart.data.datasets = data.datasets;
  152. dynamicReportChart.update();
  153. return;
  154. }
  155. dynamicReportChart = new Chart(ctx, {
  156. type: 'bar',
  157. data: data,
  158. options: {
  159. responsive: true,
  160. maintainAspectRatio: false,
  161. interaction: {
  162. mode: 'index',
  163. intersect: false,
  164. },
  165. plugins: {
  166. tooltip: {
  167. mode: 'index',
  168. intersect: false,
  169. itemSort: (a, b) => b.raw - a.raw,
  170. },
  171. legend: { display: true, position: 'bottom' },
  172. },
  173. scales: {
  174. y: { beginAtZero: true }
  175. }
  176. }
  177. });
  178. }
  179. function applyDatasetStyles(data) {
  180. if (!data?.datasets) return data;
  181. data.datasets = data.datasets.map((ds, i) => {
  182. const hue = (i * 47) % 360;
  183. return {
  184. ...ds,
  185. barThickness: 10,
  186. maxBarThickness: 10,
  187. backgroundColor: `hsla(${hue}, 70%, 55%, 0.85)`,
  188. borderColor: `hsl(${hue}, 70%, 45%)`,
  189. borderWidth: 0,
  190. };
  191. });
  192. return data;
  193. }
  194. function applyFilters() {
  195. let filter_msg = document.getElementById("filter_msg");
  196. if (filter_msg) filter_msg.style.display = "none";
  197. @this.applyFilters();
  198. }
  199. window.addEventListener('dynamic-report:updated', (e) => {
  200. buildOrUpdateChart(e.detail);
  201. });
  202. </script>
  203. @endpush