Ver Fonte

report tranne ultimo

FabioFratini há 8 meses atrás
pai
commit
c1b9fc632f

+ 260 - 120
app/Http/Livewire/Reports.php

@@ -5,8 +5,7 @@ namespace App\Http\Livewire;
 use Livewire\Component;
 use Illuminate\Support\Facades\Auth;
 use Carbon\Carbon;
-use App\Models\Receipt;
-use App\Models\ReceiptRow;
+
 use Illuminate\Support\Facades\DB;
 use Illuminate\Support\Facades\Log;
 use App\Models\Course;
@@ -15,11 +14,10 @@ use App\Models\MemberCard;
 class Reports extends Component
 {
     public $type = 'anagrafica';
-    public $yearFilter;
+    public $seasonFilter;
 
     public $courses = [];
     public $selectedCourse = null;
-    protected $listeners = ['refreshData' => '$refresh'];
 
     public function mount()
     {
@@ -29,29 +27,86 @@ class Reports extends Component
         if (isset($_GET["type"]))
             $this->type = $_GET["type"];
 
-        $this->yearFilter = Carbon::now()->year;
+        $this->seasonFilter = $this->getCurrentSeason();
         $this->courses = $this->getCoursesForSelect();
-        $this->emit('dataUpdated');
     }
 
     public function render()
     {
         return view('livewire.reports');
     }
-    public function updateCourseChart()
+
+    /**
+     * Get current season in format "2024-2025"
+     */
+    private function getCurrentSeason()
     {
-        $this->emit('courseDataUpdated');
+        $now = Carbon::now();
+        $currentYear = $now->year;
+
+        // If we're in September-December, season is current year to next year
+        // If we're in January-August, season is previous year to current year
+        if ($now->month >= 9) {
+            return $currentYear . '-' . ($currentYear + 1);
+        } else {
+            return ($currentYear - 1) . '-' . $currentYear;
+        }
     }
 
-    public function updatedSelectedCourse($value)
+    /**
+     * Get available seasons for dropdown
+     */
+    public function getAvailableSeasons()
     {
-        Log::info('Selected course changed to: ' . $value);
-        $this->emit('courseDataUpdated', $value);
+        $seasons = [];
+        $currentYear = Carbon::now()->year;
+        $startYear = 2020; // Adjust based on your data
+
+        // If current month is September or later, include next season
+        $endYear = Carbon::now()->month >= 9 ? $currentYear + 1 : $currentYear;
+
+        for ($year = $startYear; $year <= $endYear; $year++) {
+            $seasons[] = $year . '-' . ($year + 1);
+        }
+
+        return array_reverse($seasons); // Most recent first
+    }
+
+    /**
+     * Parse season string to get start and end years
+     */
+    private function parseSeason($season)
+    {
+        $parts = explode('-', $season);
+        return [
+            'start_year' => (int)$parts[0],
+            'end_year' => (int)$parts[1]
+        ];
+    }
+
+    /**
+     * Get date range for a season (September 1st to August 31st)
+     */
+    private function getSeasonDateRange($season)
+    {
+        $years = $this->parseSeason($season);
+
+        return [
+            'start' => Carbon::create($years['start_year'], 9, 1), // September 1st
+            'end' => Carbon::create($years['end_year'], 8, 31)     // August 31st
+        ];
+    }
+
+    public function setSelectedCourse($courseId)
+    {
+        $this->selectedCourse = $courseId;
+        Log::info('Selected course set to: ' . $courseId);
+        return $this->getCourseMonthlyEarnings();
     }
 
     public function getTesseratiData()
     {
-        $endYear = $this->yearFilter;
+        $endYear = $this->parseSeason($this->seasonFilter)['end_year'];
         return self::getMemberCountChartData($endYear);
     }
 
@@ -60,89 +115,174 @@ class Reports extends Component
         $this->type = $type;
     }
 
-    public function setYearFilter($year)
+    public function updateCharts()
     {
-        $this->yearFilter = $year;
-        $this->emit('dataUpdated');
+        $this->courses = $this->getCoursesForSelect();
+        $this->emit('chartsUpdated');
+        $this->dispatchBrowserEvent('chartsUpdated');
     }
 
-    public function getMonthlyTotals()
+    public function updateCourseChart()
     {
-        $year = $this->yearFilter;
+        $this->emit('chartsUpdated');
+        $this->dispatchBrowserEvent('chartsUpdated');
+    }
 
-        $months = range(1, 12);
-        $monthNames = [];
-        $incomeData = array_fill(0, 12, 0);
-        $expenseData = array_fill(0, 12, 0);
+    public function updatedSeasonFilter()
+    {
+        $this->courses = $this->getCoursesForSelect();
+        $this->emit('chartsUpdated');
+        $this->dispatchBrowserEvent('chartsUpdated');
+    }
 
-        foreach ($months as $month) {
-            $date = Carbon::createFromDate($year, $month, 1);
-            $monthNames[] = ucfirst($date->locale('it')->monthName);
-        }
+    public function setSeasonFilter($season)
+    {
+        $this->seasonFilter = $season;
+    }
 
-        $incomeReceipts = DB::table('receipts')
-            ->join('receipts_rows', 'receipts.id', '=', 'receipts_rows.receip_id')
-            ->where('receipts.year', $year)
-            ->where('receipts.type', 'IN')
-            ->select(DB::raw('MONTH(receipts.date) as month_num'), DB::raw('SUM(receipts_rows.amount) as total'))
-            ->groupBy('month_num')
-            ->get();
+public function getMonthlyTotals()
+{
+    $dateRange = $this->getSeasonDateRange($this->seasonFilter);
+    Log::info('Getting monthly totals for season: ' . $this->seasonFilter);
+
+    $monthOrder = [9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8];
+    $monthNames = ['Set', 'Ott', 'Nov', 'Dic', 'Gen', 'Feb', 'Mar', 'Apr', 'Mag', 'Giu', 'Lug', 'Ago'];
+
+    $incomeData = array_fill(0, 12, 0);
+    $expenseData = array_fill(0, 12, 0);
+    Log::info('Date range: ' . $dateRange['start'] . ' to ' . $dateRange['end']);
+
+    // Get income records with detailed logging
+    $incomeRecords = DB::table('records')
+        ->join('records_rows', 'records.id', '=', 'records_rows.record_id')
+        ->whereBetween('records.date', [$dateRange['start'], $dateRange['end']])
+        ->where('records.type', 'IN')
+        ->select(DB::raw('MONTH(records.date) as month_num'), DB::raw('SUM(records_rows.amount) as total'))
+        ->groupBy('month_num')
+        ->get();
+
+    Log::info('Income records found: ' . $incomeRecords->count());
+    foreach ($incomeRecords as $record) {
+        Log::info("Income - Month: {$record->month_num}, Total: {$record->total}");
+    }
 
-        $expenseReceipts = DB::table('receipts')
-            ->join('receipts_rows', 'receipts.id', '=', 'receipts_rows.receip_id')
-            ->where('receipts.year', $year)
-            ->where('receipts.type', 'OUT')
-            ->select(DB::raw('MONTH(receipts.date) as month_num'), DB::raw('SUM(receipts_rows.amount) as total'))
-            ->groupBy('month_num')
-            ->get();
+    // Get expense records with detailed logging
+    $expenseRecords = DB::table('records')
+        ->join('records_rows', 'records.id', '=', 'records_rows.record_id')
+        ->whereBetween('records.date', [$dateRange['start'], $dateRange['end']])
+        ->where('records.type', 'OUT')
+        ->select(DB::raw('MONTH(records.date) as month_num'), DB::raw('SUM(records_rows.amount) as total'))
+        ->groupBy('month_num')
+        ->get();
+
+    Log::info('Expense records found: ' . $expenseRecords->count());
+    foreach ($expenseRecords as $record) {
+        Log::info("Expense - Month: {$record->month_num}, Total: {$record->total}");
+    }
 
-        foreach ($incomeReceipts as $receipt) {
-            $index = $receipt->month_num - 1;
-            if (isset($incomeData[$index])) {
-                $incomeData[$index] = $receipt->total;
+    // Process income records
+    foreach ($incomeRecords as $record) {
+        $monthIndex = array_search($record->month_num, $monthOrder);
+        if ($monthIndex !== false) {
+            $incomeData[$monthIndex] = $record->total;
+
+            // Special logging for May (month 5)
+            if ($record->month_num == 5) {
+                Log::info("MAY INCOME DETECTED:");
+                Log::info("- Month number: {$record->month_num}");
+                Log::info("- Total amount: {$record->total}");
+                Log::info("- Array index: {$monthIndex}");
+                Log::info("- Month name: Mag");
+
+                // Get detailed May records for debugging
+                $mayIncomeDetails = DB::table('records')
+                    ->join('records_rows', 'records.id', '=', 'records_rows.record_id')
+                    ->whereBetween('records.date', [$dateRange['start'], $dateRange['end']])
+                    ->where('records.type', 'IN')
+                    ->whereRaw('MONTH(records.date) = 5')
+                    ->select('records.date', 'records_rows.amount')
+                    ->get();
+
+                Log::info("May income detail records count: " . $mayIncomeDetails->count());
+                foreach ($mayIncomeDetails as $detail) {
+                    Log::info("May record - Date: {$detail->date}, Amount: {$detail->amount}");
+                }
             }
         }
+    }
 
-        foreach ($expenseReceipts as $receipt) {
-            $index = $receipt->month_num - 1;
-            if (isset($expenseData[$index])) {
-                $expenseData[$index] = $receipt->total;
+    // Process expense records
+    foreach ($expenseRecords as $record) {
+        $monthIndex = array_search($record->month_num, $monthOrder);
+        if ($monthIndex !== false) {
+            $expenseData[$monthIndex] = $record->total;
+
+            // Special logging for May (month 5)
+            if ($record->month_num == 5) {
+                Log::info("MAY EXPENSE DETECTED:");
+                Log::info("- Month number: {$record->month_num}");
+                Log::info("- Total amount: {$record->total}");
+                Log::info("- Array index: {$monthIndex}");
+                Log::info("- Month name: Mag");
+
+                // Get detailed May records for debugging
+                $mayExpenseDetails = DB::table('records')
+                    ->join('records_rows', 'records.id', '=', 'records_rows.record_id')
+                    ->whereBetween('records.date', [$dateRange['start'], $dateRange['end']])
+                    ->where('records.type', 'OUT')
+                    ->whereRaw('MONTH(records.date) = 5')
+                    ->select('records.date', 'records_rows.amount')
+                    ->get();
+
+                Log::info("May expense detail records count: " . $mayExpenseDetails->count());
+                foreach ($mayExpenseDetails as $detail) {
+                    Log::info("May record - Date: {$detail->date}, Amount: {$detail->amount}");
+                }
             }
         }
-
-
-        return [
-            'labels' => $monthNames,
-            'datasets' => [
-                [
-                    'label' => 'Entrate',
-                    'data' => $incomeData,
-                    'backgroundColor' => 'rgba(54, 162, 235, 0.5)'
-                ],
-                [
-                    'label' => 'Uscite',
-                    'data' => $expenseData,
-                    'backgroundColor' => 'rgba(255, 99, 132, 0.5)'
-                ],
-            ]
-        ];
     }
 
+    // Log final arrays
+    Log::info('Final income data array: ' . json_encode($incomeData));
+    Log::info('Final expense data array: ' . json_encode($expenseData));
+
+    // Specifically log May position (index 8 in our academic year order)
+    Log::info("May position in chart:");
+    Log::info("- Income for May (index 8): " . $incomeData[8]);
+    Log::info("- Expense for May (index 8): " . $expenseData[8]);
+
+    return [
+        'labels' => $monthNames,
+        'datasets' => [
+            [
+                'label' => 'Entrate',
+                'data' => $incomeData,
+                'backgroundColor' => 'rgba(54, 162, 235, 0.5)'
+            ],
+            [
+                'label' => 'Uscite',
+                'data' => $expenseData,
+                'backgroundColor' => 'rgba(255, 99, 132, 0.5)'
+            ],
+        ]
+    ];
+}
+
     public function getYearlySummary()
     {
-        $year = $this->yearFilter;
+        $dateRange = $this->getSeasonDateRange($this->seasonFilter);
 
-        $totalIncome = DB::table('receipts')
-            ->join('receipts_rows', 'receipts.id', '=', 'receipts_rows.receip_id')
-            ->where('receipts.year', $year)
-            ->where('receipts.type', 'IN')
-            ->sum('receipts_rows.amount');
+        $totalIncome = DB::table('records')
+            ->join('records_rows', 'records.id', '=', 'records_rows.record_id')
+            ->whereBetween('records.date', [$dateRange['start'], $dateRange['end']])
+            ->where('records.type', 'IN')
+            ->sum('records_rows.amount');
 
-        $totalExpenses = DB::table('receipts')
-            ->join('receipts_rows', 'receipts.id', '=', 'receipts_rows.receip_id')
-            ->where('receipts.year', $year)
-            ->where('receipts.type', 'OUT')
-            ->sum('receipts_rows.amount');
+        $totalExpenses = DB::table('records')
+            ->join('records_rows', 'records.id', '=', 'records_rows.record_id')
+            ->whereBetween('records.date', [$dateRange['start'], $dateRange['end']])
+            ->where('records.type', 'OUT')
+            ->sum('records_rows.amount');
 
         $delta = $totalIncome - $totalExpenses;
 
@@ -155,14 +295,14 @@ class Reports extends Component
 
     public function getTopCausalsByAmount($limit = 10)
     {
-        $year = $this->yearFilter;
+        $dateRange = $this->getSeasonDateRange($this->seasonFilter);
 
-        $query = DB::table('receipts_rows')
-            ->join('receipts', 'receipts_rows.receip_id', '=', 'receipts.id')
-            ->join('causals', 'receipts_rows.causal_id', '=', 'causals.id')
-            ->where('receipts.year', $year);
+        $query = DB::table('records_rows')
+            ->join('records', 'records_rows.record_id', '=', 'records.id')
+            ->join('causals', 'records_rows.causal_id', '=', 'causals.id')
+            ->whereBetween('records.date', [$dateRange['start'], $dateRange['end']]);
 
-        $query->where('receipts.type', 'IN');
+        $query->where('records.type', 'IN');
 
         Log::info('Query: ' . $query->toSql());
 
@@ -170,14 +310,14 @@ class Reports extends Component
             'causals.id',
             'causals.name',
             'causals.parent_id',
-            DB::raw('SUM(receipts_rows.amount) as total_amount')
+            DB::raw('SUM(records_rows.amount) as total_amount')
         )
             ->groupBy('causals.id', 'causals.name', 'causals.parent_id')
             ->orderBy('total_amount', 'desc')
             ->limit($limit)
             ->get();
 
-        Log::info('Causals: ' . json_encode($causals));
+        Log::info('Causals: ' . json_encode(value: $causals));
 
         $inData = [];
 
@@ -218,11 +358,15 @@ class Reports extends Component
 
     public function getCoursesForSelect()
     {
-        $currentYear = date('Y');
+        $seasonYears = $this->parseSeason($this->seasonFilter);
 
         $courses = Course::with(['level', 'type', 'frequency'])
             ->where('active', true)
-            ->where('year', 'like', '%' . $currentYear . '%')
+            ->where(function($query) use ($seasonYears) {
+                $query->where('year', 'like', '%' . $seasonYears['start_year'] . '%')
+                      ->orWhere('year', 'like', '%' . $seasonYears['end_year'] . '%')
+                      ->orWhere('year', 'like', '%' . $this->seasonFilter . '%');
+            })
             ->orderBy('name')
             ->get()
             ->map(function ($course) {
@@ -253,32 +397,38 @@ class Reports extends Component
         return $courses;
     }
 
-
     public function getCourseMonthlyEarnings()
     {
         $courseId = $this->selectedCourse;
         Log::info('Getting earnings for course ID: ' . $courseId);
 
-        if (empty($courseId)) {
+        // September to August order for academic year
+        $monthOrder = [9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8];
+        $monthNames = [
+            9 => 'Set', 10 => 'Ott', 11 => 'Nov', 12 => 'Dic',
+            1 => 'Gen', 2 => 'Feb', 3 => 'Mar', 4 => 'Apr',
+            5 => 'Mag', 6 => 'Giu', 7 => 'Lug', 8 => 'Ago'
+        ];
 
+        if (empty($courseId)) {
             return [
-                'labels' => ['Set', 'Ott', 'Nov', 'Dic', 'Gen', 'Feb', 'Mar', 'Apr', 'Mag', 'Giu', 'Lug', 'Ago'],
+                'labels' => array_values($monthNames),
                 'datasets' => [
                     [
                         'label' => 'Pagamenti Effettuati',
                         'backgroundColor' => 'rgba(0, 184, 148, 1)',
-                        'data' => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+                        'data' => array_fill(0, 12, 0),
                         'type' => 'bar',
                         'order' => 3
                     ],
                     [
-                        'label' => 'Pagamenti Totali',
+                        'label' => 'Pagamenti Attesi',
                         'backgroundColor' => 'transparent',
                         'borderColor' => 'rgba(48, 51, 107, 1)',
                         'borderWidth' => 3,
                         'pointBackgroundColor' => 'rgba(48, 51, 107, 1)',
                         'pointRadius' => 5,
-                        'data' => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+                        'data' => array_fill(0, 12, 0),
                         'type' => 'line',
                         'tension' => 0.2,
                         'order' => 2
@@ -287,8 +437,6 @@ class Reports extends Component
             ];
         }
 
-        $monthOrder = [9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8];
-
         $monthlyData = [];
         foreach ($monthOrder as $i) {
             $monthlyData[$i] = [
@@ -327,21 +475,6 @@ class Reports extends Component
             }
         }
 
-        $monthNames = [
-            9 => 'Set',
-            10 => 'Ott',
-            11 => 'Nov',
-            12 => 'Dic',
-            1 => 'Gen',
-            2 => 'Feb',
-            3 => 'Mar',
-            4 => 'Apr',
-            5 => 'Mag',
-            6 => 'Giu',
-            7 => 'Lug',
-            8 => 'Ago',
-        ];
-
         $labels = [];
         $earnedData = [];
         $totalData = [];
@@ -400,33 +533,40 @@ class Reports extends Component
             ->whereRaw('YEAR(expire_date) <= ?', [$endYear])
             ->get();
 
-        $yearCounts = [];
+        $seasonCounts = [];
         for ($year = $startYear; $year <= $endYear; $year++) {
-            $yearPeriod = ($year - 1) . '-' . $year;
-            $yearCounts[$yearPeriod] = [];
+            $seasonPeriod = ($year - 1) . '-' . $year;
+            $seasonCounts[$seasonPeriod] = [];
         }
 
         foreach ($memberCards as $card) {
             $expireYear = date('Y', strtotime($card->expire_date));
+            $expireMonth = date('n', strtotime($card->expire_date));
+
+            // Determine which season this belongs to
+            if ($expireMonth >= 9) {
+                // September-December: belongs to season starting that year
+                $seasonPeriod = $expireYear . '-' . ($expireYear + 1);
+            } else {
+                // January-August: belongs to season starting previous year
+                $seasonPeriod = ($expireYear - 1) . '-' . $expireYear;
+            }
 
-            $previousYear = $expireYear - 1;
-            $yearPeriod = $previousYear . '-' . $expireYear;
-
-            if (isset($yearCounts[$yearPeriod])) {
-                $yearCounts[$yearPeriod][$card->member_id] = true;
+            if (isset($seasonCounts[$seasonPeriod])) {
+                $seasonCounts[$seasonPeriod][$card->member_id] = true;
             }
         }
 
-        $yearLabels = [];
+        $seasonLabels = [];
         $memberCountData = [];
 
-        foreach ($yearCounts as $yearPeriod => $members) {
-            $yearLabels[] = $yearPeriod;
+        foreach ($seasonCounts as $seasonPeriod => $members) {
+            $seasonLabels[] = $seasonPeriod;
             $memberCountData[] = count($members);
         }
 
         return [
-            'labels' => $yearLabels,
+            'labels' => $seasonLabels,
             'datasets' => [
                 [
                     'label' => 'Membri Tesserati',

+ 2 - 0
resources/views/layouts/app.blade.php

@@ -204,6 +204,8 @@
                 print "Società";
             if (Request::is('profile'))
                 print "Profilo Utente";
+            if (Request::is('reports'))
+                print "Reports";
             @endphp
             </h3>
 

+ 853 - 519
resources/views/livewire/reports.blade.php

@@ -1,579 +1,913 @@
-<!-- filepath: /Users/fabiofratini/Desktop/Projects/iao_team/resources/views/livewire/reports.blade.php -->
-<div class="col card--ui" id="card--dashboard">
-
-    <header id="title--section" style="display:none !important"
-        class="d-flex align-items-center justify-content-between">
-        <div class="title--section_name d-flex align-items-center justify-content-between">
-            <i class="ico--ui title_section utenti me-2"></i>
-            <h2 class="primary">Reports</h2>
-        </div>
+{{-- resources/views/livewire/reports.blade.php --}}
+<div>
+    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
+    <style>
+        :root {
+            --primary-color: #3b5bdb;
+            --secondary-color: #495057;
+            --success-color: #00b894;
+            --info-color: #22b8cf;
+            --warning-color: #ffd43b;
+            --danger-color: #ff6b6b;
+            --dark-color: #212529;
+            --border-color: #e9ecef;
+            --shadow-sm: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
+            --shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
+        }
 
-    </header>
+        .dashboard-container {
+            padding: 1rem;
+            max-width: 1400px;
+            margin: 0 auto;
+        }
 
+        .dashboard-header {
+            text-align: center;
+            margin-bottom: 2rem;
+            padding: 2rem;
+            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+            border-radius: 16px;
+            color: white;
+        }
 
-    <section id="subheader" class="d-flex align-items-center">
-    </section>
+        .dashboard-header h1 {
+            font-size: 2.5rem;
+            font-weight: 700;
+            margin-bottom: 0.5rem;
+        }
 
-    <section id="reports-section">
+        .dashboard-header p {
+            font-size: 1.1rem;
+            opacity: 0.9;
+        }
 
-        <div class="row">
-            <div class="col-md-12">
-                <canvas id="monthly-in-out-chart"></canvas>
-            </div>
+        .controls-section {
+            background: white;
+            border-radius: 12px;
+            padding: 1.5rem;
+            box-shadow: var(--shadow-sm);
+            border: 1px solid var(--border-color);
+            margin-bottom: 2rem;
+            display: flex;
+            gap: 2rem;
+            align-items: center;
+            flex-wrap: wrap;
+        }
 
-        </div>
-        <div class="col-md-12 chart-container">
-            <canvas id="causals-chart" style="height: 300px; max-height: 300px;"></canvas>
-        </div>
-        <div class="row mt-5">
-            <div class="col-md-12">
-                <canvas id="tesserati-chart"></canvas>
-            </div>
-        </div>
-        <div class="row mt-5">
-            <div class="col-md-6">
-                <select wire:model="selectedCourse" wire:change="updateCourseChart">
-                    <option value="">Seleziona un Corso</option>
-                    @foreach($courses as $course)
-                        <option value="{{ $course['id'] }}">{{ $course['full_name'] }}</option>
-                    @endforeach
-                </select>
-            </div>
-            <div class="col-md-12 mt-3">
-                <canvas id="courses-chart" style="height: 250px; max-height: 250px;"></canvas>
-            </div>
-        </div>
-    </section>
+        .control-group {
+            display: flex;
+            flex-direction: column;
+            gap: 0.5rem;
+        }
 
-</div>
+        .control-group label {
+            font-weight: 600;
+            font-size: 0.875rem;
+            color: var(--secondary-color);
+        }
 
-@push('scripts')
-    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
-    <script>
-        document.addEventListener('DOMContentLoaded', function () {
-            initializeChartSizes();
-
-            window.livewire.on('dataUpdated', () => {
-                updateCharts();
-                updateCausalsChart();
-            });
-
-            window.livewire.on('courseDataUpdated', async (courseId) => {
-                console.log('Course data update event received for course ID:', courseId);
-                await updateCoursesChart(courseId);
-                updateCausalsChart();
-                Object.keys(window.chartSizes).forEach(chartId => {
-                    restoreChartSize(chartId);
-                });
-            });
-
-            updateCharts();
-            updateCausalsChart();
-            updateTesseratiChart();
-
-
-            async function updateCharts() {
-                try {
-                    const monthlyData = await @this.getMonthlyTotals();
-
-                    if (window.monthlyInOutChart) {
-                        window.monthlyInOutChart.destroy();
-                    }
+        .form-select {
+            border-radius: 8px;
+            border: 2px solid var(--border-color);
+            padding: 0.75rem 1rem;
+            font-size: 1rem;
+            transition: all 0.3s ease;
+            min-width: 200px;
+        }
 
-                    const monthlyInOutCtx = document.getElementById('monthly-in-out-chart').getContext('2d');
-
-                    window.monthlyInOutChart = new Chart(monthlyInOutCtx, {
-                        type: 'bar',
-                        data: monthlyData,
-                        options: {
-                            responsive: true,
-                            scales: {
-                                x: {
-                                    title: {
-                                        display: false,
-                                        text: 'Mese'
-                                    },
-                                    grid: {
-                                        display: false
-                                    }
-                                },
-                                y: {
-                                    display: false,
-                                    title: {
-                                        display: false,
-                                        text: 'Importo (€)'
-                                    },
-                                    beginAtZero: true,
-                                    ticks: {
-                                        display: false
-                                    },
-                                    grid: {
-                                        display: false
-                                    }
-                                }
-                            },
-                            plugins: {
-                                legend: {
-                                    display: true
-                                },
-                                title: {
-                                    display: true,
-                                    text: 'Entrate/Uscite Mensili',
-                                    font: {
-                                        size: 16
-                                    }
-                                },
-                                tooltip: {
-                                    callbacks: {
-                                        label: function (context) {
-                                            let label = context.dataset.label || '';
-                                            if (label) {
-                                                label += ': ';
-                                            }
-                                            if (context.parsed.y !== null) {
-                                                label += new Intl.NumberFormat('it-IT', {
-                                                    style: 'currency',
-                                                    currency: 'EUR'
-                                                }).format(context.parsed.y);
-                                            }
-                                            return label;
-                                        }
-                                    }
-                                }
-                            }
-                        }
-                    });
+        .form-select:focus {
+            border-color: var(--primary-color);
+            box-shadow: 0 0 0 0.2rem rgba(59, 91, 219, 0.25);
+            outline: none;
+        }
+
+        .summary-cards {
+            display: grid;
+            grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
+            gap: 1rem;
+            margin-bottom: 2rem;
+        }
+
+        .summary-card {
+            background: white;
+            border-radius: 16px;
+            padding: 1.5rem;
+            box-shadow: var(--shadow-sm);
+            border: 1px solid var(--border-color);
+            text-align: center;
+            transition: transform 0.3s ease;
+        }
+
+        .summary-card:hover {
+            transform: translateY(-2px);
+        }
+
+        .summary-card h3 {
+            font-size: 0.875rem;
+            font-weight: 600;
+            color: var(--secondary-color);
+            text-transform: uppercase;
+            letter-spacing: 0.5px;
+            margin-bottom: 0.5rem;
+        }
+
+        .summary-card .value {
+            font-size: 2rem;
+            font-weight: 700;
+            margin-bottom: 0.25rem;
+        }
+
+        .summary-card.income .value { color: var(--success-color); }
+        .summary-card.expense .value { color: var(--danger-color); }
+        .summary-card.delta .value { color: var(--primary-color); }
+        .summary-card.delta.negative .value { color: var(--danger-color); }
+
+        .chart-row {
+            width: 100%;
+            margin-bottom: 2rem;
+        }
+
+        .chart-card {
+            background: white;
+            border-radius: 16px;
+            box-shadow: var(--shadow-sm);
+            border: 1px solid var(--border-color);
+            overflow: hidden;
+            transition: all 0.3s ease;
+        }
+
+        .chart-card:hover {
+            box-shadow: var(--shadow);
+        }
 
-                    const summaryData = await @this.getYearlySummary();
+        .chart-header {
+            padding: 1.5rem 2rem 1rem;
+            border-bottom: 1px solid var(--border-color);
+            background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%);
+        }
+
+        .chart-title {
+            font-size: 1.25rem;
+            font-weight: 600;
+            color: var(--dark-color);
+            margin: 0;
+        }
+
+        .chart-body {
+            padding: 2rem;
+        }
+
+        .chart-container {
+            position: relative;
+            height: 400px !important;
+            width: 100%;
+        }
+
+        .chart-container canvas {
+            max-height: 400px !important;
+            height: 400px !important;
+        }
+
+        .course-controls {
+            background: #f8f9fa;
+            border-radius: 12px;
+            padding: 1.5rem;
+            margin-bottom: 1.5rem;
+        }
+
+        .legend-container {
+            display: flex;
+            gap: 2rem;
+            margin-top: 1rem;
+            flex-wrap: wrap;
+        }
+
+        .legend-item {
+            display: flex;
+            align-items: center;
+            gap: 0.5rem;
+            font-size: 0.875rem;
+        }
+
+        .legend-color {
+            width: 12px;
+            height: 12px;
+            border-radius: 50%;
+        }
+
+        .monthly-table-container {
+            background: #f8f9fa;
+            border-radius: 12px;
+            padding: 1.5rem;
+            box-shadow: var(--shadow-sm);
+        }
+
+        .members-table-container {
+            background: #f8f9fa;
+            border-radius: 12px;
+            padding: 1.5rem;
+            box-shadow: var(--shadow-sm);
+        }
+
+        .monthly-table, .members-table {
+            font-size: 0.875rem;
+        }
+
+        .members-table .table-header {
+            display: grid;
+            grid-template-columns: 1.2fr 0.8fr 1fr;
+            gap: 0.5rem;
+            margin-bottom: 0.5rem;
+            padding-bottom: 0.5rem;
+            border-bottom: 2px solid var(--border-color);
+        }
+
+        .members-table .table-row {
+            display: grid;
+            grid-template-columns: 1.2fr 0.8fr 1fr;
+            gap: 0.5rem;
+            padding: 0.5rem 0;
+            border-bottom: 1px solid #e9ecef;
+            transition: background-color 0.2s ease;
+        }
+
+        .table-cell.season-name {
+            text-align: left;
+            font-weight: 600;
+            font-size: 0.8rem;
+        }
+
+        .table-cell.members-count {
+            text-align: center;
+            font-weight: 600;
+            color: var(--primary-color);
+        }
+
+        .table-cell.variation {
+            text-align: right;
+            font-size: 0.8rem;
+        }
+
+        .variation-positive {
+            color: var(--success-color);
+            font-weight: 600;
+        }
+
+        .variation-negative {
+            color: var(--danger-color);
+            font-weight: 600;
+        }
+
+        .variation-neutral {
+            color: var(--secondary-color);
+            font-weight: 500;
+        }
+
+        .monthly-table {
+            font-size: 0.875rem;
+        }
+
+        .table-header {
+            display: grid;
+            grid-template-columns: 1fr 1fr 1fr 1fr;
+            gap: 0.5rem;
+            margin-bottom: 0.5rem;
+            padding-bottom: 0.5rem;
+            border-bottom: 2px solid var(--border-color);
+        }
+
+        .table-row {
+            display: grid;
+            grid-template-columns: 1fr 1fr 1fr 1fr;
+            gap: 0.5rem;
+            padding: 0.5rem 0;
+            border-bottom: 1px solid #e9ecef;
+            transition: background-color 0.2s ease;
+        }
+
+        .table-row:hover {
+            background-color: rgba(0, 0, 0, 0.02);
+        }
+
+        .table-row.positive {
+            background-color: rgba(0, 184, 148, 0.05);
+        }
+
+        .table-row.negative {
+            background-color: rgba(255, 107, 107, 0.05);
+        }
+
+        .table-row.neutral {
+            background-color: rgba(73, 80, 87, 0.02);
+        }
+
+        .table-cell {
+            padding: 0.25rem 0.5rem;
+            text-align: right;
+        }
+
+        .table-header .table-cell {
+            font-weight: 600;
+            color: var(--secondary-color);
+            text-align: center;
+            text-transform: uppercase;
+            font-size: 0.75rem;
+            letter-spacing: 0.5px;
+        }
+
+        .table-cell.month-name {
+            text-align: left;
+            font-weight: 600;
+        }
 
-                } catch (error) {
-                    console.error('Error updating charts:', error);
-                    document.getElementById('monthly-in-out-chart').insertAdjacentHTML(
-                        'afterend',
-                        '<div class="alert alert-danger">Errore nel caricamento dei dati finanziari</div>'
-                    );
-                }
+        .table-cell.income {
+            color: var(--success-color);
+            font-weight: 500;
+        }
+
+        .table-cell.expense {
+            color: var(--danger-color);
+            font-weight: 500;
+        }
+
+        .table-cell.net {
+            font-weight: 600;
+        }
+
+        .table-row.positive .table-cell.net {
+            color: var(--success-color);
+        }
+
+        .table-row.negative .table-cell.net {
+            color: var(--danger-color);
+        }
+
+        .table-row.neutral .table-cell.net {
+            color: var(--secondary-color);
+        }
+
+        @media (max-width: 1024px) {
+            .chart-body > div[style*="grid-template-columns"] {
+                grid-template-columns: 1fr !important;
+                gap: 1rem !important;
             }
 
-            async function updateCausalsChart() {
-                try {
-                    const causalsData = await @this.getTopCausalsByAmount(10, 'IN');
+            .monthly-table-container {
+                order: 2;
+            }
+        }
 
-                    if (window.causalsChart) {
-                        window.causalsChart.destroy();
-                    }
+        .loading {
+            text-align: center;
+            padding: 2rem;
+            color: var(--secondary-color);
+        }
 
-                    const causalsCtx = document.getElementById('causals-chart').getContext('2d');
+        .error-message {
+            background: #fff5f5;
+            border: 1px solid #fed7d7;
+            color: #c53030;
+            padding: 1rem;
+            border-radius: 8px;
+            margin: 1rem 0;
+        }
 
-                    const existingTabs = document.querySelector('.causals-tabs');
-                    if (existingTabs) {
-                        existingTabs.remove();
-                    }
+        @media (max-width: 768px) {
+            .dashboard-container {
+                padding: 0.5rem;
+            }
 
-                    const existingTitle = document.querySelector('.causals-title');
-                    if (existingTitle) {
-                        existingTitle.remove();
-                    }
+            .dashboard-header h1 {
+                font-size: 2rem;
+            }
 
-                    const chartTitle = document.createElement('h4');
-                    chartTitle.className = 'text-center mt-2 mb-3 causals-title';
-
-                    const chartCanvas = document.getElementById('causals-chart');
-                    chartCanvas.parentNode.insertBefore(chartTitle, chartCanvas);
-
-                    const inData = causalsData.inData;
-
-                    const colors = [
-                        'rgba(54, 162, 235, 0.8)',   // Blue
-                        'rgba(75, 192, 192, 0.8)',   // Teal
-                        'rgba(153, 102, 255, 0.8)',  // Purple
-                        'rgba(255, 159, 64, 0.8)',   // Orange
-                        'rgba(39, 174, 96, 0.8)',    // Green
-                        'rgba(41, 128, 185, 0.8)',   // Dark blue
-                        'rgba(142, 68, 173, 0.8)',   // Dark purple
-                        'rgba(230, 126, 34, 0.8)',   // Dark orange
-                        'rgba(46, 204, 113, 0.8)',   // Light green
-                        'rgba(52, 152, 219, 0.8)'    // Light blue
-                    ];
-
-                    const commonOptions = {
-                        responsive: true,
-                        maintainAspectRatio: false,
-                        plugins: {
-                            title: {
-                                display: true,
-                                text: 'Causali performanti',
-                                font: {
-                                    size: 16
-                                }
-                            },
-                            tooltip: {
-                                callbacks: {
-                                    label: function (context) {
-                                        const fullName = inData[context.dataIndex]?.fullName || context.label;
-                                        const value = context.raw;
-
-                                        return fullName + ': ' + new Intl.NumberFormat('it-IT', {
-                                            style: 'currency',
-                                            currency: 'EUR'
-                                        }).format(value);
-                                    }
-                                }
-                            },
-                            legend: {
-                                display: true,
-                                position: 'right',
-                                labels: {
-                                    boxWidth: 15,
-                                    padding: 10,
-                                    generateLabels: function (chart) {
-                                        const data = chart.data;
-                                        if (data.labels.length && data.datasets.length) {
-                                            return data.labels.map(function (label, i) {
-                                                const meta = chart.getDatasetMeta(0);
-                                                const style = meta.controller.getStyle(i);
-
-                                                let shortenedLabel = label;
-                                                if (label.length > 20) {
-                                                    shortenedLabel = label.substring(0, 17) + '...';
-                                                }
-
-                                                return {
-                                                    text: shortenedLabel,
-                                                    fillStyle: style.backgroundColor,
-                                                    hidden: !chart.getDataVisibility(i),
-                                                    index: i,
-                                                    datasetIndex: 0
-                                                };
-                                            });
-                                        }
-                                        return [];
-                                    }
-                                }
-                            }
-                        }
-                    };
-
-                    let chartData = {
-                        labels: inData.map(item => item.label),
-                        datasets: [{
-                            label: 'Importo',
-                            data: inData.map(item => item.value),
-                            backgroundColor: inData.map((item, index) => colors[index % colors.length]),
-                            borderWidth: 1,
-                            borderColor: '#fff'
-                        }]
-                    };
-
-                    window.causalsChart = new Chart(causalsCtx, {
-                        type: 'doughnut',
-                        data: chartData,
-                        options: commonOptions
-                    });
-
-                } catch (error) {
-                    console.error('Error updating causals chart:', error);
-                    document.getElementById('causals-chart').insertAdjacentHTML(
-                        'afterend',
-                        '<div class="alert alert-danger">Errore nel caricamento dei dati delle causali</div>'
-                    );
-                }
+            .controls-section {
+                flex-direction: column;
+                align-items: stretch;
+                gap: 1rem;
             }
-        });
 
+            .chart-body {
+                padding: 1rem;
+            }
 
-        async function updateCoursesChart() {
-            try {
-                const courseData = await @this.getCourseMonthlyEarnings();
-                console.log('Course data received:', courseData);
+            .chart-container {
+                height: 300px !important;
+            }
 
-                if (window.coursesChart) {
-                    window.coursesChart.destroy();
-                }
+            .chart-container canvas {
+                max-height: 300px !important;
+                height: 300px !important;
+            }
 
-                const coursesCtx = document.getElementById('courses-chart').getContext('2d');
+            .legend-container {
+                gap: 1rem;
+            }
+        }
+    </style>
 
-                const dashedLinesPlugin = {
-                    // Plugin definition unchanged
-                    id: 'dashedLines',
-                    beforeDatasetsDraw: (chart) => {
-                        const ctx = chart.ctx;
-                        const lineDataset = chart.data.datasets.find(d => d.type === 'line' && d.label === 'Pagamenti Attesi');
-                        const barDataset = chart.data.datasets.find(d => d.type === 'bar' && d.label === 'Pagamenti Effettuati');
+    <div class="dashboard-container">
 
-                        if (!lineDataset || !barDataset) return;
+        <div class="controls-section">
+            <div class="control-group">
+                <label for="season-filter">Stagione di Riferimento:</label>
+                <select class="form-select" wire:model="seasonFilter" wire:change="updateCharts">
+                    @foreach($this->getAvailableSeasons() as $season)
+                        <option value="{{ $season }}">{{ $season }}</option>
+                    @endforeach
+                </select>
+            </div>
+        </div>
 
-                        const lineMeta = chart.getDatasetMeta(chart.data.datasets.indexOf(lineDataset));
-                        const barMeta = chart.getDatasetMeta(chart.data.datasets.indexOf(barDataset));
+        @php
+            $summary = $this->getYearlySummary();
+        @endphp
+        <div class="summary-cards">
+            <div class="summary-card income">
+                <h3>Entrate Totali</h3>
+                <div class="value">€{{ number_format($summary['totalIncome'], 2, ',', '.') }}</div>
+            </div>
+            <div class="summary-card expense">
+                <h3>Uscite Totali</h3>
+                <div class="value">€{{ number_format($summary['totalExpenses'], 2, ',', '.') }}</div>
+            </div>
+            <div class="summary-card delta {{ $summary['delta'] < 0 ? 'negative' : '' }}">
+                <h3>Bilancio Netto</h3>
+                <div class="value">€{{ number_format($summary['delta'], 2, ',', '.') }}</div>
+            </div>
+        </div>
 
-                        if (!lineMeta.data.length || !barMeta.data.length) return;
+        <!-- Charts Section - Force complete re-render with wire:key -->
+        <div wire:key="season-{{ $seasonFilter }}-course-{{ $selectedCourse ?? 'none' }}">
+            <div class="chart-row">
+                <div class="chart-card">
+                    <div class="chart-header">
+                        <h3 class="chart-title">Entrate e Uscite Mensili - {{ $seasonFilter }}</h3>
+                    </div>
+                    <div class="chart-body">
+                        <div style="display: grid; grid-template-columns: 1fr 300px; gap: 2rem; align-items: start;">
+                            <div class="chart-container">
+                                <canvas id="monthly-chart-{{ str_replace('-', '', $seasonFilter) }}"></canvas>
+                            </div>
+
+                            @php
+                                $monthlyTotals = $this->getMonthlyTotals();
+                                $incomeData = $monthlyTotals['datasets'][0]['data'];
+                                $expenseData = $monthlyTotals['datasets'][1]['data'];
+                                $monthNames = $monthlyTotals['labels'];
+                            @endphp
+
+                            <div class="monthly-table-container">
+                                <h4 style="margin-bottom: 1rem; font-size: 1rem; font-weight: 600; color: var(--dark-color);">Riepilogo Mensile</h4>
+                                <div class="monthly-table">
+                                    <div class="table-header">
+                                        <div class="table-cell">Mese</div>
+                                        <div class="table-cell">Entrate</div>
+                                        <div class="table-cell">Uscite</div>
+                                        <div class="table-cell">Netto</div>
+                                    </div>
+                                    @foreach($monthNames as $index => $month)
+                                        @php
+                                            $income = floatval($incomeData[$index] ?? 0);
+                                            $expense = floatval($expenseData[$index] ?? 0);
+                                            $net = $income - $expense;
+                                        @endphp
+                                        <div class="table-row {{ $net < 0 ? 'negative' : ($net > 0 ? 'positive' : 'neutral') }}">
+                                            <div class="table-cell month-name">{{ $month }}</div>
+                                            <div class="table-cell income">€{{ number_format($income, 0, ',', '.') }}</div>
+                                            <div class="table-cell expense">€{{ number_format($expense, 0, ',', '.') }}</div>
+                                            <div class="table-cell net">€{{ number_format($net, 0, ',', '.') }}</div>
+                                        </div>
+                                    @endforeach
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
 
-                        const missingData = lineDataset.missing || [];
+            <div class="chart-row">
+                <div class="chart-card">
+                    <div class="chart-header">
+                        <h3 class="chart-title">Causali Performanti - {{ $seasonFilter }}</h3>
+                    </div>
+                    <div class="chart-body">
+                        <div class="chart-container">
+                            <canvas id="causals-chart-{{ str_replace('-', '', $seasonFilter) }}"></canvas>
+                        </div>
+                    </div>
+                </div>
+            </div>
 
-                        ctx.save();
-                        ctx.lineWidth = 2;
-                        ctx.setLineDash([8, 4]);
-                        ctx.strokeStyle = 'rgba(48, 51, 107, 0.3)';
+            <div class="chart-row">
+                <div class="chart-card">
+                    <div class="chart-header">
+                        <h3 class="chart-title">Tesserati per Stagione</h3>
+                    </div>
+                    <div class="chart-body">
+                        <div style="display: grid; grid-template-columns: 1fr 300px; gap: 2rem; align-items: start;">
+                            <div class="chart-container">
+                                <canvas id="members-chart-{{ str_replace('-', '', $seasonFilter) }}"></canvas>
+                            </div>
+
+                            @php
+                                $membersData = $this->getTesseratiData();
+                                $seasonLabels = $membersData['labels'];
+                                $memberCounts = $membersData['datasets'][0]['data'];
+                            @endphp
+
+                            <div class="members-table-container">
+                                <h4 style="margin-bottom: 1rem; font-size: 1rem; font-weight: 600; color: var(--dark-color);">Riepilogo Tesserati</h4>
+                                <div class="members-table">
+                                    <div class="table-header">
+                                        <div class="table-cell">Stagione</div>
+                                        <div class="table-cell">Tesserati</div>
+                                        <div class="table-cell">Variazione</div>
+                                    </div>
+                                    @foreach($seasonLabels as $index => $season)
+                                        @php
+                                            $current = intval($memberCounts[$index] ?? 0);
+                                            $previous = $index > 0 ? intval($memberCounts[$index - 1] ?? 0) : 0;
+                                            $variation = $index > 0 ? $current - $previous : 0;
+                                            $variationPercent = $previous > 0 ? round(($variation / $previous) * 100, 1) : 0;
+                                        @endphp
+                                        <div class="table-row {{ $variation > 0 ? 'positive' : ($variation < 0 ? 'negative' : 'neutral') }}">
+                                            <div class="table-cell season-name">{{ $season }}</div>
+                                            <div class="table-cell members-count">{{ number_format($current, 0, ',', '.') }}</div>
+                                            <div class="table-cell variation">
+                                                @if($index > 0)
+                                                    @if($variation > 0)
+                                                        <span class="variation-positive">+{{ $variation }} (+{{ $variationPercent }}%)</span>
+                                                    @elseif($variation < 0)
+                                                        <span class="variation-negative">{{ $variation }} ({{ $variationPercent }}%)</span>
+                                                    @else
+                                                        <span class="variation-neutral">{{ $variation }}</span>
+                                                    @endif
+                                                @else
+                                                    <span class="variation-neutral">—</span>
+                                                @endif
+                                            </div>
+                                        </div>
+                                    @endforeach
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
 
-                        for (let i = 0; i < lineMeta.data.length; i++) {
-                            const linePoint = lineMeta.data[i];
-                            const barPoint = barMeta.data[i];
+            <div class="chart-row">
+                <div class="chart-card">
+                    <div class="chart-header">
+                        <h3 class="chart-title">Analisi Corsi</h3>
+                    </div>
+                    <div class="chart-body">
+                        <div class="course-controls">
+                            <div class="control-group">
+                                <label>Seleziona Corso:</label>
+                                <select class="form-select" wire:model="selectedCourse" wire:change="updateCourseChart">
+                                    <option value="">Seleziona un Corso</option>
+                                    @foreach($courses as $course)
+                                        <option value="{{ $course['id'] }}">{{ $course['full_name'] }}</option>
+                                    @endforeach
+                                </select>
+                            </div>
+                            <div class="legend-container">
+                                <div class="legend-item">
+                                    <div class="legend-color" style="background: rgba(0, 184, 148, 1);"></div>
+                                    <span>Pagamenti Effettuati</span>
+                                </div>
+                                <div class="legend-item">
+                                    <div class="legend-color" style="background: rgba(48, 51, 107, 1);"></div>
+                                    <span>Pagamenti Attesi</span>
+                                </div>
+                            </div>
+                        </div>
+                        <div class="chart-container">
+                            <canvas id="courses-chart-{{ str_replace('-', '', $seasonFilter) }}-{{ $selectedCourse ?? 'none' }}"></canvas>
+                        </div>
+                    </div>
+                </div>
+            </div>
 
-                            if (!linePoint || !barPoint) continue;
+            <script>
+                (function() {
+                    const seasonFilter = '{{ $seasonFilter }}';
+                    const selectedCourse = '{{ $selectedCourse ?? 'none' }}';
+                    const seasonKey = '{{ str_replace('-', '', $seasonFilter) }}';
 
-                            ctx.beginPath();
-                            ctx.moveTo(linePoint.x, linePoint.y);
-                            ctx.lineTo(linePoint.x, barPoint.y);
-                            ctx.stroke();
+                    console.log('Creating charts for season:', seasonFilter);
 
-                            if (missingData[i] && missingData[i] > 0) {
-                                const midY = (linePoint.y + barPoint.y) / 2;
-                                ctx.textAlign = 'center';
-                                ctx.font = '10px Arial';
-                                ctx.fillStyle = 'rgba(48, 51, 107, 0.8)';
-                            }
-                        }
+                    // Get the data fresh from PHP
+                    const monthlyData = @json($this->getMonthlyTotals());
+                    const causalsData = @json($this->getTopCausalsByAmount());
+                    const membersData = @json($this->getTesseratiData());
+                    const courseData = @json($this->getCourseMonthlyEarnings());
+
+                    console.log('Monthly data for', seasonFilter, ':', monthlyData);
+                    console.log('May value should be:', monthlyData.datasets[0].data[8]);
 
-                        ctx.restore();
+                    // Wait for DOM to be ready
+                    if (document.readyState === 'loading') {
+                        document.addEventListener('DOMContentLoaded', initCharts);
+                    } else {
+                        setTimeout(initCharts, 100);
                     }
-                };
-
-                window.coursesChart = new Chart(coursesCtx, {
-                    type: 'bar',
-                    plugins: [dashedLinesPlugin],
-                    data: courseData,
-                    options: {
-                        responsive: true,
-                        maintainAspectRatio: false,
-                        layout: {
-                            padding: {
-                                top: 20
-                            }
-                        },
-                        // Rest of options unchanged
-                        scales: {
-                            x: {
-                                grid: {
-                                    display: false
-                                }
+
+                    function initCharts() {
+                        createMonthlyChart();
+                        createCausalsChart();
+                        createMembersChart();
+                        createCoursesChart();
+                    }
+
+                    function createMonthlyChart() {
+                        const canvasId = `monthly-chart-${seasonKey}`;
+                        const canvas = document.getElementById(canvasId);
+                        if (!canvas) {
+                            console.log('Canvas not found:', canvasId);
+                            return;
+                        }
+
+                        const ctx = canvas.getContext('2d');
+
+                        const incomeGradient = ctx.createLinearGradient(0, 0, 0, 400);
+                        incomeGradient.addColorStop(0, 'rgba(0, 184, 148, 0.8)');
+                        incomeGradient.addColorStop(1, 'rgba(0, 184, 148, 0.2)');
+
+                        const expenseGradient = ctx.createLinearGradient(0, 0, 0, 400);
+                        expenseGradient.addColorStop(0, 'rgba(255, 107, 107, 0.8)');
+                        expenseGradient.addColorStop(1, 'rgba(255, 107, 107, 0.2)');
+
+                        new Chart(ctx, {
+                            type: 'bar',
+                            data: {
+                                labels: monthlyData.labels,
+                                datasets: [
+                                    {
+                                        label: 'Entrate',
+                                        data: monthlyData.datasets[0].data,
+                                        backgroundColor: incomeGradient,
+                                        borderColor: '#00b894',
+                                        borderWidth: 2,
+                                    },
+                                    {
+                                        label: 'Uscite',
+                                        data: monthlyData.datasets[1].data,
+                                        backgroundColor: expenseGradient,
+                                        borderColor: '#ff6b6b',
+                                        borderWidth: 2,
+                                    }
+                                ]
                             },
-                            y: {
-                                display: true,
-                                beginAtZero: true,
-                                grid: {
-                                    color: 'rgba(0, 0, 0, 0.1)',
-                                    borderDash: [5, 5]
+                            options: {
+                                responsive: true,
+                                maintainAspectRatio: false,
+                                plugins: {
+                                    legend: {
+                                        position: 'top',
+                                        labels: {
+                                            usePointStyle: true,
+                                            padding: 20,
+                                            font: { weight: '500' }
+                                        }
+                                    },
+                                    tooltip: {
+                                        backgroundColor: 'rgba(255, 255, 255, 0.95)',
+                                        titleColor: '#212529',
+                                        bodyColor: '#495057',
+                                        borderColor: '#e9ecef',
+                                        borderWidth: 1,
+                                        cornerRadius: 8,
+                                        callbacks: {
+                                            label: function(context) {
+                                                return context.dataset.label + ': €' +
+                                                       new Intl.NumberFormat('it-IT').format(context.parsed.y);
+                                            }
+                                        }
+                                    }
                                 },
-                                ticks: {
-                                    callback: function (value) {
-                                        return new Intl.NumberFormat('it-IT', {
-                                            style: 'currency',
-                                            currency: 'EUR',
-                                            maximumFractionDigits: 0
-                                        }).format(value);
+                                scales: {
+                                    x: {
+                                        grid: { display: false },
+                                        ticks: { font: { weight: '500' } }
+                                    },
+                                    y: {
+                                        beginAtZero: true,
+                                        grid: { color: 'rgba(0, 0, 0, 0.05)' },
+                                        ticks: {
+                                            callback: function(value) {
+                                                return '€' + new Intl.NumberFormat('it-IT').format(value);
+                                            }
+                                        }
                                     }
+                                },
+                                animation: {
+                                    duration: 1000,
+                                    easing: 'easeOutQuart'
                                 }
                             }
-                        },
-                        plugins: {
-                            legend: {
-                                display: true,
-                                position: 'top',
-                                align: 'center',
-                                labels: {
-                                    usePointStyle: true,
-                                    padding: 20
-                                }
-                            },
-                            title: {
-                                display: true,
-                                text: 'Pagamenti per corso',
-                                font: {
-                                    size: 16
-                                }
-                            },
-                            tooltip: {
-                                callbacks: {
-                                    label: function (context) {
-                                        if (context.dataset.label === 'Pagamenti Attesi') {
-                                            let parts = [];
-
-                                            const participants = context.dataset.participants ? context.dataset.participants[context.dataIndex] : 0;
-                                            parts.push('N° iscritti: ' + participants);
-
-                                            const expectedAmount = context.parsed.y;
-                                            parts.push('Pagamenti attesi: ' + new Intl.NumberFormat('it-IT', {
-                                                style: 'currency',
-                                                currency: 'EUR'
-                                            }).format(expectedAmount));
-
-                                            const missingAmount = context.dataset.missing ? context.dataset.missing[context.dataIndex] : 0;
-                                            parts.push('Ancora da pagare: ' + new Intl.NumberFormat('it-IT', {
-                                                style: 'currency',
-                                                currency: 'EUR'
-                                            }).format(missingAmount));
-
-                                            return parts.join(' | ');
-                                        }
+                        });
 
-                                        let label = context.dataset.label || '';
-                                        if (label) {
-                                            label += ': ';
-                                        }
+                        console.log('Monthly chart created for', seasonFilter);
+                    }
 
-                                        if (context.parsed.y !== null) {
-                                            label += new Intl.NumberFormat('it-IT', {
-                                                style: 'currency',
-                                                currency: 'EUR'
-                                            }).format(context.parsed.y);
+                    function createCausalsChart() {
+                        const canvasId = `causals-chart-${seasonKey}`;
+                        const canvas = document.getElementById(canvasId);
+                        if (!canvas) return;
+
+                        const ctx = canvas.getContext('2d');
+
+                        const colors = [
+                            'rgba(59, 91, 219, 0.8)',
+                            'rgba(0, 184, 148, 0.8)',
+                            'rgba(34, 184, 207, 0.8)',
+                            'rgba(255, 212, 59, 0.8)',
+                            'rgba(255, 107, 107, 0.8)',
+                            'rgba(142, 68, 173, 0.8)',
+                            'rgba(230, 126, 34, 0.8)',
+                            'rgba(149, 165, 166, 0.8)',
+                            'rgba(241, 196, 15, 0.8)',
+                            'rgba(231, 76, 60, 0.8)'
+                        ];
+
+                        new Chart(ctx, {
+                            type: 'doughnut',
+                            data: {
+                                labels: causalsData.inLabels,
+                                datasets: [{
+                                    label: 'Importo',
+                                    data: causalsData.inData.map(item => item.value),
+                                    backgroundColor: colors,
+                                    borderColor: colors.map(color => color.replace('0.8', '1')),
+                                    borderWidth: 2,
+                                    hoverOffset: 8
+                                }]
+                            },
+                            options: {
+                                responsive: true,
+                                maintainAspectRatio: false,
+                                cutout: '60%',
+                                plugins: {
+                                    legend: {
+                                        position: 'left',
+                                        labels: {
+                                            usePointStyle: true,
+                                            padding: 15,
+                                            font: { size: 11, weight: '500' }
+                                        }
+                                    },
+                                    tooltip: {
+                                        backgroundColor: 'rgba(255, 255, 255, 0.95)',
+                                        titleColor: '#212529',
+                                        bodyColor: '#495057',
+                                        borderColor: '#e9ecef',
+                                        borderWidth: 1,
+                                        cornerRadius: 8,
+                                        callbacks: {
+                                            label: function(context) {
+                                                const value = context.raw;
+                                                const total = context.dataset.data.reduce((a, b) => a + b, 0);
+                                                const percentage = Math.round((value / total) * 100);
+                                                return context.label + ': €' +
+                                                       new Intl.NumberFormat('it-IT').format(value) +
+                                                       ` (${percentage}%)`;
+                                            }
                                         }
-
-                                        return label;
                                     }
+                                },
+                                animation: {
+                                    animateRotate: true,
+                                    duration: 1000
                                 }
                             }
-                        },
-                        elements: {
-                            point: {
-                                radius: 4,
-                                hoverRadius: 6
-                            },
-                            line: {
-                                tension: 0.4
-                            }
-                        }
+                        });
                     }
-                });
-
-                // Maintain chart dimensions
-                coursesCtx.canvas.style.height = '250px';
-                coursesCtx.canvas.style.maxHeight = '250px';
-
-            } catch (error) {
-                console.error('Error updating courses chart:', error);
-                document.getElementById('courses-chart').insertAdjacentHTML(
-                    'afterend',
-                    '<div class="alert alert-danger">Errore nel caricamento dei dati del corso</div>'
-                );
-            }
-        }
-
-        async function updateTesseratiChart() {
-            try {
-                const tesseratiData = await @this.getTesseratiData();
-
-                if (window.tesseratiChart) {
-                    window.tesseratiChart.destroy();
-                }
 
-                const tesseratiCtx = document.getElementById('tesserati-chart').getContext('2d');
-
-                window.tesseratiChart = new Chart(tesseratiCtx, {
-                    type: 'line',
-                    data: tesseratiData,
-                    options: {
-                        responsive: true,
-                        scales: {
-                            x: {
-                                title: {
-                                    display: true,
-                                    text: 'Anno Tesseramento'
-                                },
-                                grid: {
-                                    display: false
-                                }
+                    function createMembersChart() {
+                        const canvasId = `members-chart-${seasonKey}`;
+                        const canvas = document.getElementById(canvasId);
+                        if (!canvas) return;
+
+                        const ctx = canvas.getContext('2d');
+
+                        const gradient = ctx.createLinearGradient(0, 0, 0, 400);
+                        gradient.addColorStop(0, 'rgba(59, 91, 219, 0.3)');
+                        gradient.addColorStop(1, 'rgba(59, 91, 219, 0.05)');
+
+                        new Chart(ctx, {
+                            type: 'line',
+                            data: {
+                                labels: membersData.labels,
+                                datasets: [{
+                                    label: 'Membri Tesserati',
+                                    data: membersData.datasets[0].data,
+                                    borderColor: '#3b5bdb',
+                                    backgroundColor: gradient,
+                                    borderWidth: 3,
+                                    fill: true,
+                                    tension: 0.4,
+                                    pointBackgroundColor: '#3b5bdb',
+                                    pointBorderColor: '#ffffff',
+                                    pointBorderWidth: 2,
+                                    pointRadius: 6,
+                                    pointHoverRadius: 8
+                                }]
                             },
-                            y: {
-                                title: {
-                                    display: true,
-                                    text: 'Numero di Tesserati'
+                            options: {
+                                responsive: true,
+                                maintainAspectRatio: false,
+                                plugins: {
+                                    legend: { display: false },
+                                    tooltip: {
+                                        backgroundColor: 'rgba(255, 255, 255, 0.95)',
+                                        titleColor: '#212529',
+                                        bodyColor: '#495057',
+                                        borderColor: '#e9ecef',
+                                        borderWidth: 1,
+                                        cornerRadius: 8,
+                                        callbacks: {
+                                            label: function(context) {
+                                                return 'Tesserati: ' + context.parsed.y;
+                                            }
+                                        }
+                                    }
+                                },
+                                scales: {
+                                    x: { grid: { display: false } },
+                                    y: {
+                                        beginAtZero: true,
+                                        grid: { color: 'rgba(0, 0, 0, 0.05)' },
+                                        ticks: { precision: 0 }
+                                    }
                                 },
-                                beginAtZero: true,
-                                ticks: {
-                                    precision: 0
+                                animation: {
+                                    duration: 1000,
+                                    easing: 'easeOutQuart'
                                 }
                             }
-                        },
-                        plugins: {
-                            legend: {
-                                display: true,
-                                position: 'top'
-                            },
-                            title: {
-                                display: true,
-                                text: 'Andamento Tesserati per Anno',
-                                font: {
-                                    size: 16
-                                }
+                        });
+                    }
+
+                    function createCoursesChart() {
+                        const canvasId = `courses-chart-${seasonKey}-${selectedCourse}`;
+                        const canvas = document.getElementById(canvasId);
+                        if (!canvas) return;
+
+                        const ctx = canvas.getContext('2d');
+
+                        new Chart(ctx, {
+                            type: 'bar',
+                            data: {
+                                labels: courseData.labels,
+                                datasets: courseData.datasets
                             },
-                            tooltip: {
-                                callbacks: {
-                                    label: function (context) {
-                                        let label = context.dataset.label || '';
-                                        if (label) {
-                                            label += ': ';
+                            options: {
+                                responsive: true,
+                                maintainAspectRatio: false,
+                                scales: {
+                                    x: { grid: { display: false } },
+                                    y: {
+                                        beginAtZero: true,
+                                        grid: {
+                                            color: 'rgba(0, 0, 0, 0.1)',
+                                            borderDash: [5, 5]
+                                        },
+                                        ticks: {
+                                            callback: function(value) {
+                                                return '€' + new Intl.NumberFormat('it-IT').format(value);
+                                            }
                                         }
-                                        if (context.parsed.y !== null) {
-                                            label += context.parsed.y + ' tesserati';
+                                    }
+                                },
+                                plugins: {
+                                    legend: { display: false },
+                                    tooltip: {
+                                        backgroundColor: 'rgba(255, 255, 255, 0.95)',
+                                        titleColor: '#212529',
+                                        bodyColor: '#495057',
+                                        borderColor: '#e9ecef',
+                                        borderWidth: 1,
+                                        cornerRadius: 8,
+                                        callbacks: {
+                                            label: function(context) {
+                                                return context.dataset.label + ': €' +
+                                                       new Intl.NumberFormat('it-IT').format(context.parsed.y);
+                                            }
                                         }
-                                        return label;
                                     }
+                                },
+                                animation: {
+                                    duration: 1000,
+                                    easing: 'easeOutQuart'
                                 }
                             }
-                        }
+                        });
                     }
-                });
-            } catch (error) {
-                console.error('Error updating tesserati chart:', error);
-                document.getElementById('tesserati-chart').insertAdjacentHTML(
-                    'afterend',
-                    '<div class="alert alert-danger">Errore nel caricamento dei dati tesserati</div>'
-                );
-            }
-        }
-
-        document.addEventListener('DOMContentLoaded', function () {
-            const selectElement = document.querySelector('select[name="selectedCourse"]');
-            if (selectElement) {
-                selectElement.addEventListener('change', function () {
-                    const selectedValue = this.value;
-                    console.log('Selected course ID:', selectedValue);
-                    @this.set('selectedCourse', selectedValue);
-                });
-            }
-        });
-
-        function initializeChartSizes() {
-            window.chartSizes = {
-                'monthly-in-out-chart': {
-                    height: document.getElementById('monthly-in-out-chart').style.height || 'auto',
-                    maxHeight: document.getElementById('monthly-in-out-chart').style.maxHeight || 'none'
-                },
-                'causals-chart': {
-                    height: '300px',
-                    maxHeight: '300px'
-                },
-                'tesserati-chart': {
-                    height: document.getElementById('tesserati-chart').style.height || 'auto',
-                    maxHeight: document.getElementById('tesserati-chart').style.maxHeight || 'none'
-                },
-                'courses-chart': {
-                    height: '250px',
-                    maxHeight: '250px'
-                }
-            };
-        }
-
-        function restoreChartSize(chartId) {
-            if (!window.chartSizes || !window.chartSizes[chartId]) return;
-
-            const canvas = document.getElementById(chartId);
-            if (canvas) {
-                canvas.style.height = window.chartSizes[chartId].height;
-                canvas.style.maxHeight = window.chartSizes[chartId].maxHeight;
-            }
-        }
-
+                })();
+            </script>
+        </div>
 
-    </script>
-@endpush
+    </div>
+</div>