FabioFratini 6 kuukautta sitten
vanhempi
commit
56d07eb1a3

+ 626 - 103
app/Http/Livewire/Dashboard.php

@@ -4,10 +4,11 @@ namespace App\Http\Livewire;
 
 use Livewire\Component;
 use Carbon\Carbon;
+use Illuminate\Support\Facades\Log;
 
 class Dashboard extends Component
 {
-
+    // Existing properties
     public $totMembers = 0;
     public $totSuppliers = 0;
     public $totTodayIn = 0;
@@ -17,164 +18,686 @@ class Dashboard extends Component
     public $out;
     public $members;
 
+    // New properties for the enhanced dashboard
+    public $activeUsers = 0;
+    public $registeredUsers = 0;
+    public $expiredCertificates = 0;
+    public $suspendedSubscriptions = 0;
+    public $activeUsersChange = 0;
+    public $registeredUsersChange = 0;
+    public $expiredCertificatesChange = 0;
+    public $suspendedSubscriptionsChange = 0;
+
+    public $toReceive = 0;
+    public $toPay = 0;
+
+    public $courses = [];
+    public $fields = [];
+    public $recentUsers = [];
+    public $recentTransactions = [];
+    public $coursesParticipation = [];
+    public $notes = '';
+    public $savedNotes = []; // Array to store saved notes
+
     public array $membersDatas = [];
     public array $recordDatas = [];
     public array $labels = [];
+    public array $monthlyLabels = [];
+    public array $monthlyIncomeData = [];
+    public array $monthlyExpenseData = [];
 
     public function render()
     {
+        Log::info('Dashboard render method called');
         return view('livewire.dashboard');
     }
 
     public function mount()
     {
+        Log::info('Dashboard mount started');
+        $startTime = microtime(true);
 
         $this->dayName = Carbon::now()->locale('it_IT')->dayName;
+        Log::info('Day name set', ['day' => $this->dayName]);
+
+        $this->loadBasicStats();
+        $this->loadUserStats();
+        $this->loadFinancialStats();
+        $this->loadRecentData();
+        $this->loadSavedNotes();
+
+        $endTime = microtime(true);
+        $executionTime = round(($endTime - $startTime) * 1000, 2);
+        Log::info('Dashboard mount completed', [
+            'execution_time_ms' => $executionTime,
+            'active_users' => $this->activeUsers,
+            'courses_count' => count($this->courses),
+            'participation_count' => count($this->coursesParticipation)
+        ]);
+    }
+
+    private function loadBasicStats()
+    {
+        Log::info('Loading basic stats');
+        $startTime = microtime(true);
+
+        try {
+            $this->totMembers = \App\Models\Member::count();
+            $this->totSuppliers = \App\Models\Supplier::count();
+            Log::info('Basic counts loaded', [
+                'total_members' => $this->totMembers,
+                'total_suppliers' => $this->totSuppliers
+            ]);
+
+            // Calculate today's income and expenses
+            $this->totTodayIn = 0;
+            $todayRecordsIn = \App\Models\Record::where('type', 'IN')
+                ->where('date', date("Y-m-d"))
+                ->get();
 
-        $this->totMembers = \App\Models\Member::count();
-        $this->totSuppliers = \App\Models\Supplier::count();
-        $this->totTodayIn = 0;
-        $tmp = \App\Models\Record::where('type', 'IN')->where('date', date("Y-m-d"))->get();
-        foreach($tmp as $t)
-        {
-            foreach($t->rows as $r)
-            {
-                $this->totTodayIn += $r->amount;
+            foreach($todayRecordsIn as $record) {
+                foreach($record->rows as $row) {
+                    $this->totTodayIn += $row->amount;
+                }
             }
-        }
-        //$this->totTodayIn = \App\Models\Record::where('type', 'IN')->where('date', date("Y-m-d"))->rows->sum('amount');
-        $tmp = \App\Models\Record::where('type', 'OUT')->where('date', date("Y-m-d"))->get();
-        foreach($tmp as $t)
-        {
-            foreach($t->rows as $r)
-            {
-                $this->totTodayOut += $r->amount;
+
+            $this->totTodayOut = 0;
+            $todayRecordsOut = \App\Models\Record::where('type', 'OUT')
+                ->where('date', date("Y-m-d"))
+                ->get();
+
+            foreach($todayRecordsOut as $record) {
+                foreach($record->rows as $row) {
+                    $this->totTodayOut += $row->amount;
+                }
             }
+
+            $endTime = microtime(true);
+            Log::info('Basic stats loaded successfully', [
+                'today_income' => $this->totTodayIn,
+                'today_expenses' => $this->totTodayOut,
+                'execution_time_ms' => round(($endTime - $startTime) * 1000, 2)
+            ]);
+
+        } catch (\Exception $e) {
+            Log::error('Error loading basic stats', [
+                'error' => $e->getMessage(),
+                'file' => $e->getFile(),
+                'line' => $e->getLine()
+            ]);
         }
-        //$this->totTodayOut = \App\Models\Record::where('type', 'OUT')->where('date', date("Y-m-d"))->rows->sum('amount');
-
-        $this->members = \App\Models\Member::whereBetween('created_at', [date("y-m-d", strtotime('-7 days')), date("Y-m-d 23:59:59")])->select(\DB::raw("COUNT(*) as total, created_at"))->groupBy('created_at')->get();
-
-        $this->in = \App\Models\Record::where('type', 'IN')->whereBetween('date', [date("y-m-d", strtotime('-7 days')), date("Y-m-d 23:59:59")])->select(\DB::raw("SUM(amount) as total, date"))->groupBy('date')->get();
-        $this->out = \App\Models\Record::where('type', 'OUT')->whereBetween('date', [date("y-m-d", strtotime('-7 days')), date("Y-m-d 23:59:59")])->select(\DB::raw("SUM(amount) as total, date"))->groupBy('date')->get();
-
-        $this->labels = $this->getLabels();
-
-        $this->memberDatas = [
-            [
-                'label' => 'Utenti',
-                'backgroundColor' => 'blue',
-                'borderColor' => 'blue',
-                // 'data' => $this->getRandomData(),
-                'data' => $this->getMemberData(),
-            ]
-        ];
-
-        $this->recordDatas = [
-            [
-                'label' => 'Entrate',
-                'backgroundColor' => 'green',
-                'borderColor' => 'green',
-                // 'data' => $this->getRandomData(),
-                'data' => $this->getRecordData('IN'),
-            ],
-            [
-                'label' => 'Uscite',
-                'backgroundColor' => 'red',
-                'borderColor' => 'red',
-                'data' => $this->getRecordData('OUT'),
-            ]
-        ];
     }
 
-    private function getLabels()
+    private function loadUserStats()
     {
-        $labels = array();
-        for($i=0; $i<=7; $i++)
-        {
-            $labels[] = date("d/M", strtotime('-' . $i . ' days'));
+        Log::info('Loading user stats');
+        $startTime = microtime(true);
+
+        try {
+            $this->activeUsers = \App\Models\Member::where('is_archived', 0)->orWhere('is_archived', NULL)->count();
+            $this->registeredUsers = \App\Models\Member::where('current_status', 2)->count();
+            $this->suspendedSubscriptions = \App\Models\Member::where('current_status', 1)->count();
+
+            Log::info('User counts loaded', [
+                'active_users' => $this->activeUsers,
+                'registered_users' => $this->registeredUsers,
+                'suspended_subscriptions' => $this->suspendedSubscriptions
+            ]);
+
+            $this->expiredCertificates = \App\Models\Member::whereHas('certificates', function($query) {
+                $query->where('expire_date', '<', now());
+            })->whereDoesntHave('certificates', function($query) {
+                $query->where('expire_date', '>=', now());
+            })->count();
+
+            Log::info('Expired certificates count', ['expired_certificates' => $this->expiredCertificates]);
+
+            // Calculate changes from last month
+            $lastMonth = now()->subMonth();
+            $endOfLastMonth = $lastMonth->copy()->endOfMonth();
+
+            $lastMonthActiveUsers = \App\Models\Member::where('is_archived', false)
+                ->where('created_at', '<=', $endOfLastMonth)
+                ->count();
+            $lastMonthRegisteredUsers = \App\Models\Member::where('current_status', 2)
+                ->where('updated_at', '<=', $endOfLastMonth)
+                ->count();
+            $lastMonthSuspendedSubscriptions = \App\Models\Member::where('current_status', 1)
+                ->where('updated_at', '<=', $endOfLastMonth)
+                ->count();
+            $lastMonthExpiredCertificates = \App\Models\Member::whereHas('certificates', function($query) use ($endOfLastMonth) {
+                $query->where('expire_date', '<', $endOfLastMonth);
+            })->whereDoesntHave('certificates', function($query) use ($endOfLastMonth) {
+                $query->where('expire_date', '>=', $endOfLastMonth);
+            })->count();
+
+            $this->activeUsersChange = $this->activeUsers - $lastMonthActiveUsers;
+            $this->registeredUsersChange = $this->registeredUsers - $lastMonthRegisteredUsers;
+            $this->expiredCertificatesChange = $this->expiredCertificates - $lastMonthExpiredCertificates;
+            $this->suspendedSubscriptionsChange = $this->suspendedSubscriptions - $lastMonthSuspendedSubscriptions;
+
+            $endTime = microtime(true);
+            Log::info('User stats loaded successfully', [
+                'changes' => [
+                    'active_users' => $this->activeUsersChange,
+                    'registered_users' => $this->registeredUsersChange,
+                    'expired_certificates' => $this->expiredCertificatesChange,
+                    'suspended_subscriptions' => $this->suspendedSubscriptionsChange
+                ],
+                'execution_time_ms' => round(($endTime - $startTime) * 1000, 2)
+            ]);
+
+        } catch (\Exception $e) {
+            Log::error('Error loading user stats', [
+                'error' => $e->getMessage(),
+                'file' => $e->getFile(),
+                'line' => $e->getLine()
+            ]);
         }
-        return array_reverse($labels);
     }
 
-    private function getRecordData($type)
+    private function loadFinancialStats()
     {
-        $data = [];
-        for($i=0; $i<=7; $i++)
-        {
-            if ($type == 'IN')
-            {
-                $found = false;
-                foreach($this->in as $in)
-                {
-                    if (date("Y-m-d", strtotime($in->date)) == date("Y-m-d", strtotime('-' . $i . ' days')))
-                    {
-                        $data[] = $in->total;
-                        $found = true;
-                    }
+        Log::info('Loading financial stats');
+        $startTime = microtime(true);
+
+        try {
+            $currentMonth = now()->format('Y-m');
+            Log::info('Calculating financial stats for month', ['month' => $currentMonth]);
+
+            $this->toReceive = \App\Models\Record::where('type', 'IN')
+                ->whereRaw('DATE_FORMAT(date, "%Y-%m") = ?', [$currentMonth])
+                ->where(function ($query) {
+                    $query->where('deleted', false)->orWhere('deleted', null);
+                })
+                ->sum('amount') ?? 0;
+
+            $this->toPay = \App\Models\Record::where('type', 'OUT')
+                ->whereRaw('DATE_FORMAT(date, "%Y-%m") = ?', [$currentMonth])
+                ->where(function ($query) {
+                    $query->where('deleted', false)->orWhere('deleted', null);
+                })
+                ->sum('amount') ?? 0;
+
+            $endTime = microtime(true);
+            Log::info('Financial stats loaded successfully', [
+                'to_receive' => $this->toReceive,
+                'to_pay' => $this->toPay,
+                'execution_time_ms' => round(($endTime - $startTime) * 1000, 2)
+            ]);
+
+        } catch (\Exception $e) {
+            Log::error('Error loading financial stats', [
+                'error' => $e->getMessage(),
+                'file' => $e->getFile(),
+                'line' => $e->getLine()
+            ]);
+        }
+    }
+
+    private function loadRecentData()
+    {
+        Log::info('Loading recent data');
+        $startTime = microtime(true);
+
+        try {
+            // Load recent users
+            $recentMembers = \App\Models\Member::where('is_archived', 0)
+                ->orWhere('is_archived', NULL)
+                ->orderBy('created_at', 'desc')
+                ->limit(5)
+                ->get();
+
+            $this->recentUsers = $recentMembers->map(function($member) {
+                return [
+                    'surname' => strtoupper($member->last_name),
+                    'name' => strtoupper($member->first_name),
+                    'phone' => $member->phone ?? '',
+                    'email' => $member->email ?? ''
+                ];
+            })->toArray();
+
+            Log::info('Recent users loaded', ['count' => count($this->recentUsers)]);
+
+            // Load recent transactions
+            $recentRecords = \App\Models\Record::where('date', '>=', now()->subDays(30))
+                ->with(['member', 'supplier'])
+                ->orderBy('date', 'desc')
+                ->orderBy('created_at', 'desc')
+                ->limit(10)
+                ->get();
+
+            $this->recentTransactions = $recentRecords->map(function($record) {
+                if ($record->type == 'IN') {
+                    $name = $record->member ?
+                        strtoupper($record->member->last_name) . ' ' . strtoupper($record->member->first_name) :
+                        'MEMBRO SCONOSCIUTO';
+                } else {
+                    $name = $record->supplier ?
+                        strtoupper($record->supplier->name) :
+                        'FORNITORE SCONOSCIUTO';
                 }
-                if (!$found)
-                    $data[] = 0;
-            }
-            if ($type == 'OUT')
-            {
-                $found = false;
-                foreach($this->out as $out)
-                {
-                    if (date("Y-m-d", strtotime($out->date)) == date("Y-m-d", strtotime('-' . $i . ' days')))
-                    {
-                        $data[] = $out->total;
-                        $found = true;
+
+                $totalAmount = 0;
+                foreach($record->rows as $row) {
+                    $totalAmount += $row->amount;
+                }
+
+                return [
+                    'name' => $name,
+                    'amount' => $totalAmount,
+                    'type' => $record->type == 'IN' ? 'ENTRATA' : 'USCITA'
+                ];
+            })->toArray();
+
+            Log::info('Recent transactions loaded', ['count' => count($this->recentTransactions)]);
+
+            $this->loadCoursesData();
+            $this->loadCoursesParticipation();
+
+            $endTime = microtime(true);
+            Log::info('Recent data loaded successfully', [
+                'execution_time_ms' => round(($endTime - $startTime) * 1000, 2)
+            ]);
+
+        } catch (\Exception $e) {
+            Log::error('Error loading recent data', [
+                'error' => $e->getMessage(),
+                'file' => $e->getFile(),
+                'line' => $e->getLine()
+            ]);
+        }
+    }
+
+    private function loadCoursesData()
+    {
+        Log::info('Loading courses data');
+        $startTime = microtime(true);
+
+        try {
+            $today = now()->format('N');
+            $dayNames = [
+                1 => 'lun', 2 => 'mar', 3 => 'mer', 4 => 'gio',
+                5 => 'ven', 6 => 'sab', 7 => 'dom'
+            ];
+            $todayName = $dayNames[$today];
+
+            Log::info('Searching courses for today', [
+                'today_number' => $today,
+                'today_name' => $todayName
+            ]);
+
+            // Try with status = 0 first (inactive), then status = 1 (active) as fallback
+            $activeCourses = \App\Models\MemberCourse::with(['course', 'member'])
+                ->whereIn('status', [0, 1]) // Include both statuses
+                ->whereRaw('JSON_EXTRACT(`when`, "$[*].day") LIKE ?', ['%"' . $todayName . '"%'])
+                ->get();
+
+            Log::info('Raw query for courses', [
+                'today_name' => $todayName,
+                'query_like' => '%"' . $todayName . '"%',
+                'total_member_courses' => \App\Models\MemberCourse::count()
+            ]);
+
+            // Debug: let's also try a direct query to see what we get
+            $allMemberCourses = \App\Models\MemberCourse::with(['course'])
+                ->limit(10)
+                ->get();
+
+            Log::info('Sample member courses from database', [
+                'sample_courses' => $allMemberCourses->map(function($mc) {
+                    return [
+                        'id' => $mc->id,
+                        'course_id' => $mc->course_id,
+                        'course_name' => $mc->course->name ?? 'No name',
+                        'status' => $mc->status,
+                        'when' => $mc->when
+                    ];
+                })->toArray()
+            ]);
+
+            Log::info('Active courses found', [
+                'count' => $activeCourses->count(),
+                'courses_ids' => $activeCourses->pluck('id')->toArray()
+            ]);
+
+            $this->courses = $activeCourses->map(function($memberCourse) use ($todayName) {
+                $whenData = json_decode($memberCourse->when, true);
+
+                Log::debug('Processing course when data', [
+                    'member_course_id' => $memberCourse->id,
+                    'when_data' => $whenData,
+                    'looking_for_day' => $todayName
+                ]);
+
+                $todaySchedule = null;
+
+                if (is_array($whenData)) {
+                    foreach($whenData as $schedule) {
+                        if (isset($schedule['day']) && is_array($schedule['day']) && in_array($todayName, $schedule['day'])) {
+                            $todaySchedule = $schedule;
+                            Log::debug('Found matching schedule', [
+                                'schedule' => $schedule,
+                                'member_course_id' => $memberCourse->id
+                            ]);
+                            break;
+                        }
                     }
                 }
-                if (!$found)
-                    $data[] = 0;
-            }
+
+                if ($todaySchedule) {
+                    $days = implode('-', array_map('ucfirst', $todaySchedule['day']));
+
+                    return [
+                        'time' => $todaySchedule['from'] . ' - ' . $todaySchedule['to'],
+                        'course_name' => $memberCourse->course->name ?? 'Corso Sconosciuto',
+                        'days' => $days,
+                        'type' => $memberCourse->course->type ?? 'Standard'
+                    ];
+                } else {
+                    Log::debug('No matching schedule found for today', [
+                        'member_course_id' => $memberCourse->id,
+                        'when_data' => $whenData
+                    ]);
+                }
+                return null;
+            })->filter()->values()->toArray();
+
+            $this->courses = array_slice($this->courses, 0, 5);
+
+            $endTime = microtime(true);
+            Log::info('Courses data loaded successfully', [
+                'final_courses_count' => count($this->courses),
+                'execution_time_ms' => round(($endTime - $startTime) * 1000, 2),
+                'courses' => $this->courses
+            ]);
+
+        } catch (\Exception $e) {
+            Log::error('Error loading courses data', [
+                'error' => $e->getMessage(),
+                'file' => $e->getFile(),
+                'line' => $e->getLine()
+            ]);
+            $this->courses = [];
         }
+    }
+
+    private function loadCoursesParticipation()
+    {
+        Log::info('Loading courses participation');
+        $startTime = microtime(true);
+
+        try {
+            // Conta le partecipazioni per corso (include tutti gli status)
+            $courseStats = \App\Models\MemberCourse::with('course')
+                ->whereIn('status', [0, 1]) // Include both statuses
+                ->selectRaw('course_id, COUNT(*) as participants')
+                ->groupBy('course_id')
+                ->orderBy('participants', 'desc')
+                ->limit(4)
+                ->get();
+
+            Log::info('Course participation stats', [
+                'courses_found' => $courseStats->count(),
+                'stats' => $courseStats->map(function($stat) {
+                    return [
+                        'course_id' => $stat->course_id,
+                        'course_name' => $stat->course->name ?? 'Unknown',
+                        'participants' => $stat->participants
+                    ];
+                })->toArray()
+            ]);
+
+            $totalParticipants = $courseStats->sum('participants');
 
-        return array_reverse($data);
+            $this->coursesParticipation = $courseStats->map(function($stat) use ($totalParticipants) {
+                $percentage = $totalParticipants > 0 ? ($stat->participants / $totalParticipants) * 100 : 0;
+                $courseName = $stat->course->name ?? 'Corso Sconosciuto';
+
+                // Assegna colori basati sul nome del corso
+                $color = $this->getCourseColor($courseName);
+
+                return [
+                    'course_name' => $courseName,
+                    'participants' => $stat->participants,
+                    'percentage' => round($percentage, 1),
+                    'color' => $color
+                ];
+            })->toArray();
+
+            $endTime = microtime(true);
+            Log::info('Courses participation loaded successfully', [
+                'total_participants' => $totalParticipants,
+                'participation_data' => $this->coursesParticipation,
+                'execution_time_ms' => round(($endTime - $startTime) * 1000, 2)
+            ]);
+
+        } catch (\Exception $e) {
+            Log::error('Error loading courses participation', [
+                'error' => $e->getMessage(),
+                'file' => $e->getFile(),
+                'line' => $e->getLine()
+            ]);
+            $this->coursesParticipation = [];
+        }
     }
 
-    private function getMemberData()
+    private function getCourseColor($courseName)
     {
-        $data = [];
-        for($i=0; $i<=7; $i++)
-        {
-            $found = false;
-            foreach($this->members as $member)
-            {
-                if (date("Y-m-d", strtotime($member->created_at)) == date("Y-m-d", strtotime('-' . $i . ' days')))
-                {
-                    $data[] = $member->total;
-                    $found = true;
-                }
+        $courseName = strtolower($courseName);
+        $color = 'default';
+
+        if (strpos($courseName, 'padel') !== false) {
+            $color = 'padel'; // #FFD700
+        } elseif (strpos($courseName, 'tennis') !== false) {
+            $color = 'tennis'; // #8B4CF7
+        } elseif (strpos($courseName, 'pallavolo') !== false || strpos($courseName, 'volley') !== false) {
+            $color = 'pallavolo'; // #FF6B35
+        } elseif (strpos($courseName, 'yoga') !== false) {
+            $color = 'yoga'; // #339E8E
+        }
+
+        Log::debug('Course color assigned', [
+            'course_name' => $courseName,
+            'assigned_color' => $color
+        ]);
+
+        return $color;
+    }
+
+    private function loadSavedNotes()
+    {
+        Log::info('Loading saved notes');
+
+        try {
+            // Load saved notes from session or database
+            $this->savedNotes = session()->get('dashboard_notes', []);
+
+            Log::info('Saved notes loaded', [
+                'notes_count' => count($this->savedNotes)
+            ]);
+
+        } catch (\Exception $e) {
+            Log::error('Error loading saved notes', [
+                'error' => $e->getMessage()
+            ]);
+            $this->savedNotes = [];
+        }
+    }
+
+    private function saveSavedNotes()
+    {
+        try {
+            // Save notes to session (you can change this to save to database)
+            session()->put('dashboard_notes', $this->savedNotes);
+
+            Log::info('Notes saved to session', [
+                'notes_count' => count($this->savedNotes)
+            ]);
+
+        } catch (\Exception $e) {
+            Log::error('Error saving notes', [
+                'error' => $e->getMessage()
+            ]);
+        }
+    }
+
+    public function saveNote()
+    {
+        Log::info('Save note called', ['note_text' => $this->notes]);
+
+        try {
+            if (trim($this->notes) !== '') {
+                $newNote = [
+                    'id' => uniqid(),
+                    'text' => trim($this->notes),
+                    'created_at' => now()->format('d/m/Y H:i'),
+                    'completed' => false
+                ];
+
+                // Add note to the beginning of the array
+                array_unshift($this->savedNotes, $newNote);
+
+                // Save to session/database
+                $this->saveSavedNotes();
+
+                // Clear the input
+                $this->notes = '';
+
+                // Emit event for success message
+                $this->dispatchBrowserEvent('note-saved');
+
+                Log::info('Note saved successfully', [
+                    'note_id' => $newNote['id'],
+                    'total_notes' => count($this->savedNotes)
+                ]);
+            } else {
+                Log::warning('Attempted to save empty note');
             }
-            if (!$found)
-                $data[] = 0;
 
+        } catch (\Exception $e) {
+            Log::error('Error saving note', [
+                'error' => $e->getMessage(),
+                'file' => $e->getFile(),
+                'line' => $e->getLine()
+            ]);
         }
+    }
+
+    public function completeNote($noteId)
+    {
+        Log::info('Complete note called', ['note_id' => $noteId]);
 
-        return array_reverse($data);
+        try {
+            $initialCount = count($this->savedNotes);
+
+            // Find and remove the note from savedNotes
+            $this->savedNotes = array_filter($this->savedNotes, function($note) use ($noteId) {
+                return $note['id'] !== $noteId;
+            });
+
+            // Reindex the array
+            $this->savedNotes = array_values($this->savedNotes);
+
+            $finalCount = count($this->savedNotes);
+
+            if ($initialCount > $finalCount) {
+                // Save to session/database
+                $this->saveSavedNotes();
+
+                // Emit event for success message
+                $this->dispatchBrowserEvent('note-completed');
+
+                Log::info('Note completed successfully', [
+                    'note_id' => $noteId,
+                    'remaining_notes' => $finalCount
+                ]);
+            } else {
+                Log::warning('Note not found for completion', ['note_id' => $noteId]);
+            }
+
+        } catch (\Exception $e) {
+            Log::error('Error completing note', [
+                'note_id' => $noteId,
+                'error' => $e->getMessage(),
+                'file' => $e->getFile(),
+                'line' => $e->getLine()
+            ]);
+        }
     }
 
+    // Existing methods with logging
     public function addMember()
     {
+        Log::info('Redirecting to add member');
         return redirect()->to('/members?new=1');
     }
 
     public function addSupplier()
     {
+        Log::info('Redirecting to add supplier');
         return redirect()->to('/suppliers?new=1');
     }
 
     public function addIn()
     {
+        Log::info('Redirecting to add income record');
         return redirect()->to('/in?new=1');
     }
 
     public function addOut()
     {
+        Log::info('Redirecting to add expense record');
         return redirect()->to('/out?new=1');
     }
 
+    // Existing methods (keeping original implementation)
+    private function getLabels()
+    {
+        $labels = array();
+        for($i = 6; $i >= 0; $i--) {
+            $labels[] = date("d/M", strtotime('-' . $i . ' days'));
+        }
+        return $labels;
+    }
+
+    private function getRecordData($type)
+    {
+        $data = [];
+        for($i = 6; $i >= 0; $i--) {
+            $found = false;
+            $records = $type == 'IN' ? $this->in : $this->out;
+
+            foreach($records as $record) {
+                if (date("Y-m-d", strtotime($record->date)) == date("Y-m-d", strtotime('-' . $i . ' days'))) {
+                    $data[] = $record->total;
+                    $found = true;
+                    break;
+                }
+            }
+            if (!$found) {
+                $data[] = 0;
+            }
+        }
+        return $data;
+    }
+
+    private function getMemberData()
+    {
+        $data = [];
+        for($i = 6; $i >= 0; $i--) {
+            $found = false;
+            foreach($this->members as $member) {
+                if (date("Y-m-d", strtotime($member->created_at)) == date("Y-m-d", strtotime('-' . $i . ' days'))) {
+                    $data[] = $member->total;
+                    $found = true;
+                    break;
+                }
+            }
+            if (!$found) {
+                $data[] = 0;
+            }
+        }
+        return $data;
+    }
 }

+ 0 - 32
app/Http/Livewire/Reminder.php

@@ -39,17 +39,6 @@ class Reminder extends Component
     {
 
         $data = [];
-
-        /*
-        if ($this->filterT)
-        {
-
-            foreach($member_cards as $member_card)
-            {
-                $data[] = array('type' => 'Tessera', 'first_name' => $member_card->member->first_name, "last_name" => $member_card->member->last_name, 'date' => $member_card->expire_date);
-            }
-        }*/
-
         $member_cards = \App\Models\MemberCard::with('member')->where('expire_date', '>', date("y-m-d"));
         if ($this->filterFrom != '')
             $member_cards = $member_cards->where('expire_date', '>=', $this->filterFrom);
@@ -97,21 +86,6 @@ class Reminder extends Component
                 $data[] = array('type' => 'Tessera ' . $member_card->card->name, 'first_name' => $member_card->member->first_name, "last_name" => $member_card->member->last_name, 'date' => $member_card->expire_date);
             }
         }
-        /*
-        if ($this->filterC)
-        {
-            $member_certificates = \App\Models\MemberCertificate::with('member')->where('expire_date', '>', date("y-m-d"));
-            if ($this->filterFrom != '')
-                $member_certificates = $member_certificates->where('expire_date', '>=', $this->filterFrom);
-            if ($this->filterTo != '')
-                $member_certificates = $member_certificates->where('expire_date', '<=', $this->filterTo);
-            $member_certificates = $member_certificates->orderBy('expire_date')->get();
-            foreach($member_certificates as $member_certificate)
-            {
-                $data[] = array('type' => 'Certificato', 'first_name' => $member_certificate->member->first_name, "last_name" => $member_certificate->member->last_name, 'date' => $member_certificate->expire_date);
-            }
-        }
-        */
         if ($data)
         {
             $key_values = array_column($data, 'date');
@@ -122,12 +96,6 @@ class Reminder extends Component
         {
             $this->records = [];
         }
-
-        /*if ($this->sortAsc)
-            usort($this->records, function ($a, $b) {return $a[$this->sortField] > $b[$this->sortField];});
-        else
-            usort($this->records, function ($a, $b) {return $a[$this->sortField] < $b[$this->sortField];});*/
-
         $this->emit('load-data-table');
 
         return view('livewire.reminders');

+ 12 - 3
app/Http/Livewire/Supplier.php

@@ -14,7 +14,7 @@ class Supplier extends Component
 
     public $searchTxt;
     public $search;
-
+    public $showArchived = false;
     protected $rules = [
         'name' => 'required',
         'vat' => 'nullable|unique:suppliers,vat',
@@ -95,10 +95,18 @@ class Supplier extends Component
 
     public function render()
     {
-        $this->records = \App\Models\Supplier::with('nation')->get();
+        if ($this->showArchived) {
+            // Show all suppliers including archived ones
+            $this->records = \App\Models\Supplier::orderBy('name')->get();
+        } else {
+            // Show only non-archived suppliers
+            $this->records = \App\Models\Supplier::where(function($query) {
+                $query->where('archived', 0)->orWhereNull('archived');
+            })->orderBy('name')->get();
+        }
+
         return view('livewire.supplier');
     }
-
     public function hydrate()
     {
         $this->emit('load-select');
@@ -259,6 +267,7 @@ class Supplier extends Component
                 'referent_email' => null,
                 'referent_phone' => null,
                 'referent_mobile' => null,
+                'archived' => true, // Mark as archived
                 'enabled' => false // Also disable the supplier
             ]);
 

+ 55 - 0
app/Models/DashboardNote.php

@@ -0,0 +1,55 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Model;
+use Illuminate\Support\Str;
+
+class DashboardNote extends Model
+{
+    use HasFactory;
+
+    protected $fillable = [
+        'unique_id',
+        'text',
+        'completed',
+        'user_id'
+    ];
+
+    protected $casts = [
+        'completed' => 'boolean',
+        'created_at' => 'datetime',
+        'updated_at' => 'datetime'
+    ];
+
+    protected static function boot()
+    {
+        parent::boot();
+
+        static::creating(function ($note) {
+            if (empty($note->unique_id)) {
+                $note->unique_id = Str::uuid();
+            }
+        });
+    }
+
+    public function user()
+    {
+        return $this->belongsTo(User::class);
+    }
+
+    public function scopeActive($query)
+    {
+        return $query->where('completed', false);
+    }
+
+    public function scopeForUser($query, $userId = null)
+    {
+        if ($userId) {
+            return $query->where('user_id', $userId);
+        }
+
+        return $query->whereNull('user_id');
+    }
+}

+ 2 - 1
app/Models/Supplier.php

@@ -27,7 +27,8 @@ class Supplier extends Model
         'referent_email',
         'referent_phone',
         'referent_mobile',
-        'enabled'
+        'enabled',
+        'archived',
     ];
 
     public function nation()

+ 33 - 0
database/migrations/2025_07_04_075532_add_archived_to_suppliers_table.php

@@ -0,0 +1,33 @@
+<?php
+
+use App\Database\Migrations\TenantMigration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+return new class extends TenantMigration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::table('suppliers', function (Blueprint $table) {
+            $table->boolean('archived')->default(false);
+            $table->index('archived');
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::table('suppliers', function (Blueprint $table) {
+            //
+        });
+    }
+};

+ 37 - 0
database/migrations/2025_07_04_102429_add_dashboard_note_table.php

@@ -0,0 +1,37 @@
+
+<?php
+
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+use App\Database\Migrations\TenantMigration;
+return new class extends TenantMigration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('dashboard_notes', function (Blueprint $table) {
+            $table->id();
+            $table->string('unique_id')->unique();
+            $table->text('text');
+            $table->boolean('completed')->default(false);
+            $table->unsignedBigInteger('user_id')->nullable();
+            $table->timestamps();
+
+            $table->index(['user_id', 'completed', 'created_at']);
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('dashboard_notes');
+    }
+};

+ 606 - 120
resources/views/livewire/dashboard.blade.php

@@ -1,137 +1,623 @@
-<div class="col card--ui" id="card--dashboard">
-
-    <main id="dashboard" class="d-flex">
-    <section id="dash_anagrafica">
-        <div class="anagrafica--btn">
-            <h1>Anagrafica</h1>
-            <div class="anagrafica--btn_wrapper w-100 d-flex">
-
-                <div class="card--ui card--ui_btnDash utente d-flex justify-content-between me-3" wire:click="addMember()"  style="cursor: pointer;">
-                    <header class="d-flex justify-content-between">
-                        <div class="card-title d-flex align-items-start"><i class="ico--ui medium user me-2"></i><h2><small>Nuovo</small><br>Utente</h2></div><a href="/members?new=1"><i class="ico--ui big add"></i></a>
-                    </header>
-                    <footer class="d-flex justify-content-between align-items-end">
-                        <div class="card-footer_percentage d-flex">
-                            <!--<i class="ico--ui small uscite ico me-1"></i><span>10%</span>-->
-                        </div>
-                        <div class="card-footer_info text-end">
-                            <span>{{$totMembers}} </span> persone registrate
-                        </div>
-                    </footer>
-                </div>
-                <div class="card--ui card--ui_btnDash fornitore d-flex justify-items-between"  wire:click="addSupplier()"  style="cursor: pointer;">
-                    <header class="d-flex justify-content-between"><div class="card-title d-flex align-items-start"><i class="ico--ui medium fornitore me-2"></i><h2><small>Nuovo</small><br>Fornitore</h2></div><a href="/suppliers?new=1"><i class="ico--ui big add"></i></a>
-                    </header>
-                    <footer class="d-flex justify-content-between align-items-end">
-                        <div class="card-footer_percentage d-flex">
-                            <!--<i class="ico--ui small uscite ico me-1"></i><span>10%</span>-->
-                        </div>
-                        <div class="card-footer_info text-end">
-                            <span>{{$totSuppliers}} </span> fornitori registrati
-                        </div>
-                    </footer>
-                </div>
+<div class="dashboard-container">
+    <style>
+        .dashboard-container {
+            background: #F6F7FF;
+            min-height: 100vh;
+            padding: 20px;
+            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
+        }
+
+        .dashboard-grid {
+            display: grid;
+            grid-template-columns: 1fr 1fr 1fr;
+            gap: 20px;
+            margin-bottom: 20px;
+        }
+
+        .dashboard-section {
+            background: white;
+            border-radius: 12px;
+            padding: 20px;
+            box-shadow: 0 2px 10px rgba(0,0,0,0.05);
+        }
+
+        .stat-card {
+            background: white;
+            border-radius: 12px;
+            padding: 20px;
+            box-shadow: 0 2px 10px rgba(0,0,0,0.05);
+            position: relative;
+        }
+
+        .stat-card-header {
+            display: flex;
+            justify-content: space-between;
+            align-items: center;
+            margin-bottom: 10px;
+        }
+
+        .stat-card-title {
+            font-size: 14px;
+            color: #666;
+            font-weight: 500;
+        }
+
+        .stat-card-value {
+            font-size: 48px;
+            font-weight: bold;
+            color: #333;
+            margin: 10px 0;
+        }
+
+        .stat-card-change {
+            font-size: 12px;
+            color: #666;
+        }
+
+        .stat-card-change.positive {
+            color: #339E8E;
+        }
+
+        .stat-card-change.negative {
+            color: #D6234F;
+        }
+
+        .stat-icon {
+            width: 24px;
+            height: 24px;
+            border-radius: 4px;
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            color: white;
+            font-size: 12px;
+        }
+
+        .courses-list {
+            max-height: 300px;
+            overflow-y: auto;
+        }
+
+        .course-item {
+            padding: 12px;
+            border-left: 4px solid #7438FA;
+            margin-bottom: 8px;
+            background: #F6F7FF;
+            border-radius: 0 8px 8px 0;
+        }
+
+        .course-time {
+            font-weight: bold;
+            color: #333;
+            font-size: 14px;
+        }
+
+        .course-name {
+            font-size: 13px;
+            color: #7438FA;
+            font-weight: 600;
+        }
+
+        .course-days {
+            font-size: 12px;
+            color: #666;
+        }
+
+        .fields-grid {
+            display: grid;
+            grid-template-columns: 1fr 1fr;
+            gap: 10px;
+        }
+
+        .field-item {
+            padding: 12px;
+            border: 2px solid #339E8E;
+            border-radius: 8px;
+            text-align: center;
+            background: white;
+        }
+
+        .field-item.occupied {
+            border-color: #D6234F;
+            background: #FFF5F7;
+        }
+
+        .field-name {
+            font-weight: bold;
+            color: #333;
+        }
+
+        .field-time {
+            color: #666;
+            font-size: 12px;
+        }
+
+        .notes-section {
+            background: #F6F7FF;
+            border-radius: 8px;
+            padding: 15px;
+            margin-top: 15px;
+        }
+
+        .notes-input {
+            width: 100%;
+            border: none;
+            background: transparent;
+            outline: none;
+            font-size: 14px;
+            min-height: 60px;
+            resize: vertical;
+        }
+
+        .save-btn {
+            background: #7438FA;
+            color: white;
+            border: none;
+            padding: 8px 16px;
+            border-radius: 6px;
+            font-size: 12px;
+            cursor: pointer;
+            margin-top: 10px;
+        }
+
+        .save-btn:hover {
+            background: #6028E0;
+        }
+
+        .notes-list {
+            max-height: 200px;
+            overflow-y: auto;
+            margin-bottom: 15px;
+        }
+
+        .note-item {
+            display: flex;
+            align-items: flex-start;
+            gap: 10px;
+            padding: 10px;
+            background: white;
+            border-radius: 8px;
+            margin-bottom: 8px;
+            border-left: 3px solid #7438FA;
+        }
+
+        .note-checkbox {
+            width: 18px;
+            height: 18px;
+            border: 2px solid #7438FA;
+            border-radius: 4px;
+            background: white;
+            cursor: pointer;
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            color: white;
+            font-size: 12px;
+            font-weight: bold;
+            transition: all 0.2s ease;
+            flex-shrink: 0;
+            margin-top: 2px;
+        }
+
+        .note-checkbox:hover {
+            background: #7438FA;
+            transform: scale(1.1);
+        }
+
+        .note-content {
+            flex: 1;
+        }
+
+        .note-text {
+            color: #333;
+            font-size: 14px;
+            line-height: 1.4;
+            margin-bottom: 5px;
+        }
+
+        .note-date {
+            color: #666;
+            font-size: 11px;
+        }
+
+        .empty-notes {
+            text-align: center;
+            color: #666;
+            font-size: 13px;
+            padding: 20px;
+            font-style: italic;
+        }
+
+        .chart-container {
+            background: white;
+            border-radius: 12px;
+            padding: 20px;
+            box-shadow: 0 2px 10px rgba(0,0,0,0.05);
+            grid-column: span 3;
+        }
+
+        .financial-cards {
+            display: grid;
+            grid-template-columns: 1fr 1fr;
+            gap: 20px;
+            margin-bottom: 20px;
+        }
+
+        .financial-card {
+            background: white;
+            border-radius: 12px;
+            padding: 20px;
+            box-shadow: 0 2px 10px rgba(0,0,0,0.05);
+            text-align: center;
+        }
+
+        .financial-card.income {
+            border-left: 4px solid #339E8E;
+        }
+
+        .financial-card.expense {
+            border-left: 4px solid #D6234F;
+        }
+
+        .financial-amount {
+            font-size: 36px;
+            font-weight: bold;
+            margin: 10px 0;
+        }
+
+        .financial-amount.income {
+            color: #339E8E;
+        }
+
+        .financial-amount.expense {
+            color: #D6234F;
+        }
+
+        .recent-users-table {
+            width: 100%;
+            border-collapse: collapse;
+        }
+
+        .recent-users-table th,
+        .recent-users-table td {
+            text-align: left;
+            padding: 12px 8px;
+            border-bottom: 1px solid #f0f0f0;
+        }
+
+        .recent-users-table th {
+            background: #F6F7FF;
+            font-weight: 600;
+            color: #333;
+            font-size: 12px;
+        }
+
+        .recent-users-table td {
+            font-size: 14px;
+            color: #333;
+        }
+
+        .transaction-list {
+            max-height: 300px;
+            overflow-y: auto;
+        }
+
+        .transaction-item {
+            display: flex;
+            justify-content: space-between;
+            align-items: center;
+            padding: 12px;
+            border-bottom: 1px solid #f0f0f0;
+        }
+
+        .transaction-name {
+            font-weight: 500;
+            color: #333;
+        }
+
+        .transaction-amount {
+            font-weight: bold;
+        }
+
+        .transaction-type {
+            font-size: 10px;
+            padding: 4px 8px;
+            border-radius: 12px;
+            color: white;
+            font-weight: bold;
+        }
+
+        .transaction-type.income {
+            background: #339E8E;
+        }
+
+        .transaction-type.expense {
+            background: #D6234F;
+        }
+
+        .participation-bar {
+            height: 20px;
+            background: #f0f0f0;
+            border-radius: 10px;
+            overflow: hidden;
+            margin: 8px 0;
+        }
+
+        .participation-fill {
+            height: 100%;
+            transition: width 0.3s ease;
+        }
+
+        .participation-fill.padel {
+            background: #FFD700;
+        }
+
+        .participation-fill.tennis {
+            background: #8B4CF7;
+        }
+
+        .participation-fill.pallavolo {
+            background: #FF6B35;
+        }
+
+        .participation-fill.yoga {
+            background: #339E8E;
+        }
+
+        .section-title {
+            font-size: 18px;
+            font-weight: bold;
+            color: #333;
+            margin-bottom: 20px;
+        }
+
+        .chart-title {
+            font-size: 16px;
+            font-weight: 600;
+            color: #333;
+            margin-bottom: 15px;
+        }
+
+        .grid-4 {
+            display: grid;
+            grid-template-columns: repeat(4, 1fr);
+            gap: 15px;
+            margin-bottom: 20px;
+        }
+
+        .grid-3 {
+            display: grid;
+            grid-template-columns: repeat(3, 1fr);
+            gap: 20px;
+            margin-bottom: 20px;
+        }
+
+        .grid-2 {
+            display: grid;
+            grid-template-columns: repeat(2, 1fr);
+            gap: 20px;
+            margin-bottom: 20px;
+        }
+
+        .full-width {
+            grid-column: span 3;
+        }
+
+        .half-width {
+            grid-column: span 2;
+        }
+
+        .fade-out {
+            opacity: 0;
+            transform: translateX(100%);
+            transition: all 0.3s ease;
+        }
+    </style>
+
+    <div class="grid-4">
+        <div class="stat-card">
+            <div class="stat-card-header">
+                <div class="stat-card-title">Utenti Totali</div>
+                <div class="stat-icon">👥</div>
             </div>
+            <div class="stat-card-value">{{$activeUsers}}</div>
         </div>
-        <div class="anagrafica_chart">
-            <h1>Utenti iscritti ultimi 7 giorni</h1>
-            <canvas id="userChart"></canvas>
+
+        <div class="stat-card">
+            <div class="stat-card-header">
+                <div class="stat-card-title">Tesserati</div>
+                <div class="stat-icon">📋</div>
+            </div>
+            <div class="stat-card-value">{{$registeredUsers}}</div>
+        </div>
+
+        <div class="stat-card">
+            <div class="stat-card-header">
+                <div class="stat-card-title">Certificati medici scaduti</div>
+                <div class="stat-icon">📄</div>
+            </div>
+            <div class="stat-card-value">{{$expiredCertificates}}</div>
+        </div>
+
+        <div class="stat-card">
+            <div class="stat-card-header">
+                <div class="stat-card-title">Abbonamenti sospesi</div>
+                <div class="stat-icon">⏸️</div>
+            </div>
+            <div class="stat-card-value">{{$suspendedSubscriptions}}</div>
+        </div>
+    </div>
+
+    <div class="grid-3">
+        <div class="dashboard-section">
+            <div class="section-title">Ultimi utenti registrati</div>
+            @if(count($recentUsers) > 0)
+            <table class="recent-users-table">
+                <thead>
+                    <tr>
+                        <th>Cognome</th>
+                        <th>Nome</th>
+                        <th>Telefono</th>
+                        <th>Email</th>
+                    </tr>
+                </thead>
+                <tbody>
+                    @foreach($recentUsers as $user)
+                    <tr>
+                        <td>{{$user['surname']}}</td>
+                        <td>{{$user['name']}}</td>
+                        <td>{{$user['phone']}}</td>
+                        <td>{{$user['email']}}</td>
+                    </tr>
+                    @endforeach
+                </tbody>
+            </table>
+            @else
+            <div style="text-align: center; color: #666; padding: 40px;">
+                Nessun utente registrato di recente
+            </div>
+            @endif
         </div>
-        </section>
-        <section id="dash_contabilita">
-        <div class="contabilita--btn">
-            <h1>Contabilità</h1>
-            <div class="contabilita--btn_wrapper w-100 d-flex">
-                <div class="card--ui card--ui_btnDash entrata d-flex justify-items-between me-3"  wire:click="addIn()"  style="cursor: pointer;">
-                    <header class="d-flex justify-content-between"><div class="card-title d-flex align-items-start"><h2><small>Registra</small><br>Nuova Entrata</h2></div><a href="/in?new=1"><i class="ico--ui big add primary"></i></a>
-                    </header>
-                    <footer class="d-flex justify-content-between align-items-end">
-                        <div class="card-footer_percentage d-flex">
-                            <!--<i class="ico--ui small entrate ico me-1"></i><span>10%</span>-->
-                        </div>
-                        <div class="card-footer_info text-end">
-                            <span><strong>+ € {{$totTodayIn}}</strong></span> entrate oggi
-                        </div>
-                    </footer>
+
+        <div class="dashboard-section">
+            <div class="section-title">Corsi</div>
+            @if(count($courses) > 0)
+            <div class="courses-list">
+                @foreach($courses as $course)
+                <div class="course-item">
+                    <div class="course-time">{{$course['time']}}</div>
+                    <div class="course-name">{{$course['course_name']}}</div>
+                    <div class="course-days">{{$course['days']}}</div>
                 </div>
-                <div class="card--ui card--ui_btnDash uscite d-flex justify-items-between"  wire:click="addOut()"  style="cursor: pointer;">
-                    <header class="d-flex justify-content-between"><div class="card-title d-flex align-items-start"><h2><small>Registra</small><br>Nuova Uscita</h2></div><a href="/out?new=1"><i class="ico--ui big add secondary"></i></a>
-                    </header>
-                    <footer class="d-flex justify-content-between align-items-end">
-                        <div class="card-footer_percentage d-flex">
-                            <!--<i class="ico--ui small uscite ico me-1"></i><span>10%</span>-->
-                        </div>
-                        <div class="card-footer_info text-end">
-                            <span><strong>- € {{$totTodayOut}}</strong></span> uscite oggi
-                        </div>
-                    </footer>
+                @endforeach
+            </div>
+            @else
+            <div style="text-align: center; color: #666; padding: 40px;">
+                Nessun corso programmato per oggi
+            </div>
+            @endif
+        </div>
+
+        <div class="dashboard-section">
+            <div class="section-title">To do</div>
+            <div style="font-size: 14px; color: #666; margin-bottom: 10px;">{{date('d/m/Y')}}</div>
+
+            @if(count($savedNotes) > 0)
+            <div class="notes-list">
+                @foreach($savedNotes as $note)
+                <div class="note-item">
+                    <div class="note-checkbox" wire:click="completeNote('{{$note['id']}}')" title="Segna come completato">
+                        ✓
+                    </div>
+                    <div class="note-content">
+                        <div class="note-text">{{$note['text']}}</div>
+                        <div class="note-date">{{$note['created_at']}}</div>
+                    </div>
                 </div>
+                @endforeach
+            </div>
+            @else
+            <div class="empty-notes">
+                Nessuna nota salvata
+            </div>
+            @endif
+
+            <div class="notes-section">
+                <textarea class="notes-input" placeholder="Inserisci una nuova nota..." wire:model="notes"></textarea>
+                <button class="save-btn" wire:click="saveNote">SALVA</button>
             </div>
         </div>
-        <div class="contabilita--chart">
-            <h1>Entrate/Uscite ultimi 7 giorni</h1>
-            <canvas id="recordChart"></canvas>
+    </div>
+
+    <div class="grid-2">
+        <div class="dashboard-section">
+            <div class="section-title">Corsi con più partecipazioni</div>
+            @if(count($coursesParticipation) > 0)
+            <div style="padding: 10px 0;">
+                @foreach($coursesParticipation as $course)
+                <div style="margin-bottom: 20px;">
+                    <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 5px;">
+                        <span style="font-weight: 600; color: #333; font-size: 14px;">{{$course['course_name']}}</span>
+                        <span style="font-size: 12px; color: #666;">{{$course['participants']}} partecipanti</span>
+                    </div>
+                    <div class="participation-bar">
+                        <div class="participation-fill {{$course['color']}}" style="width: {{$course['percentage']}}%"></div>
+                    </div>
+                </div>
+                @endforeach
+            </div>
+            @else
+            <div style="text-align: center; color: #666; padding: 40px;">
+                Nessun corso con partecipazioni
+            </div>
+            @endif
         </div>
-        </section>
 
-    </main>
+        <div>
+            <div class="financial-cards" style="margin-bottom: 0;">
+                <div class="financial-card income">
+                    <div style="font-size: 14px; color: #666; margin-bottom: 10px;">Incassato mese corrente</div>
+                    <div class="financial-amount income">€ {{number_format($toReceive, 2)}}</div>
+                </div>
 
+                <div class="financial-card expense">
+                    <div style="font-size: 14px; color: #666; margin-bottom: 10px;">Pagato mese corrente</div>
+                    <div class="financial-amount expense">€ {{number_format($toPay, 2)}}</div>
+                </div>
+            </div>
+        </div>
+    </div>
+
+    <div class="dashboard-section">
+        <div class="section-title">Ultimi movimenti finanziari</div>
+        @if(count($recentTransactions) > 0)
+        <div class="transaction-list">
+            @foreach($recentTransactions as $transaction)
+            <div class="transaction-item">
+                <div class="transaction-name">{{$transaction['name']}}</div>
+                <div style="display: flex; align-items: center; gap: 10px;">
+                    <div class="transaction-amount">€ {{number_format($transaction['amount'], 2)}}</div>
+                    <div class="transaction-type {{$transaction['type'] == 'ENTRATA' ? 'income' : 'expense'}}">
+                        {{$transaction['type']}}
+                    </div>
+                </div>
+            </div>
+            @endforeach
+        </div>
+        @else
+        <div style="text-align: center; color: #666; padding: 40px;">
+            Nessun movimento finanziario recente
+        </div>
+        @endif
+    </div>
 </div>
 
 @push('scripts')
-    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
-@endpush
+<script>
+    window.addEventListener('note-saved', event => {
+        // Show success message
+        if (typeof toastr !== 'undefined') {
+            toastr.success('Nota salvata con successo!');
+        } else {
+            alert('Nota salvata con successo!');
+        }
+    });
 
+    window.addEventListener('note-completed', event => {
+        if (typeof toastr !== 'undefined') {
+            toastr.success('Nota completata!');
+        } else {
+            alert('Nota completata!');
+        }
+    });
 
-@push('scripts')
-    <script>
-        const chart = new Chart(
-            document.getElementById('recordChart'), {
-                type: 'line',
-                data: {
-                    labels: @json($labels),
-                    datasets: @json($recordDatas)
-                },
-                options: {
-                    plugins: {
-                        legend: {
-                            position: 'bottom'
-                        }
-                    },
-                    responsive: true,
-                    elements: {
-                        line: {
-                            tension : 0.4  // smooth lines
-                        },
-                    },
-                }
-            }
-        );
-        const chartX = new Chart(
-            document.getElementById('userChart'), {
-                type: 'line',
-                data: {
-                    labels: @json($labels),
-                    datasets: @json($memberDatas)
-                },
-                options: {
-                    plugins: {
-                        legend: {
-                            position: 'bottom'
-                        }
-                    },
-                    responsive: true,
-                    elements: {
-                        line: {
-                            tension : 0.4  // smooth lines
-                        },
-                    },
-                }
+    document.addEventListener('keydown', function(e) {
+        if (e.ctrlKey && e.key === 'Enter') {
+            let textarea = document.querySelector('.notes-input');
+            if (textarea === document.activeElement) {
+                Livewire.emit('saveNote');
             }
-        );
-        Livewire.on('updateChart', data => {
-            chart.data = data;
-            chart.update();
-        });
-    </script>
+        }
+    });
+</script>
 @endpush