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(); foreach ($todayRecordsIn as $record) { foreach ($record->rows as $row) { $this->totTodayIn += $row->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() ]); } } private function loadUserStats() { 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() ]); } } private function loadFinancialStats() { Log::info('Loading financial stats'); $startTime = microtime(true); try { $currentMonth = now()->format('Y-m'); $currentDate = now()->format('Y-m-d'); Log::info('Calculating financial stats for month', ['month' => $currentMonth]); $this->received = \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->paid = \App\Models\Record::where('type', 'OUT') ->whereRaw('DATE_FORMAT(date, "%Y-%m") = ?', [$currentMonth]) ->where('data_pagamento', '<=', $currentDate) ->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) use($currentDate) { $query->where('data_pagamento', '>', $currentDate) ->orWhereNull('data_pagamento'); }) ->where(function ($query) { $query->where('deleted', false)->orWhere('deleted', null); }) ->sum('amount') ?? 0; $endTime = microtime(true); Log::info('Financial stats loaded successfully', [ 'received' => $this->received, 'paid' => $this->paid, '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'; } $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 ]); $memberCourses = \App\Models\MemberCourse::with(['course.level', 'course.frequency', 'member']) ->whereIn('status', [0, 1]) ->whereHas('course', function ($query) { $query->whereNotNull('when'); }) ->get(); Log::info('Total member courses found', [ 'count' => $memberCourses->count() ]); $activeCourses = $memberCourses->filter(function ($memberCourse) use ($todayName) { try { $whenData = json_decode($memberCourse->course->when, true); if (!is_array($whenData)) { return false; } foreach ($whenData as $schedule) { if ( isset($schedule['day']) && is_array($schedule['day']) && in_array($todayName, $schedule['day']) ) { return true; } } } catch (\Exception $e) { Log::debug('Error parsing course schedule', [ 'member_course_id' => $memberCourse->id, 'course_id' => $memberCourse->course->id, 'when' => $memberCourse->course->when, 'error' => $e->getMessage() ]); } return false; }); Log::info('Active courses found for today', [ 'count' => $activeCourses->count(), 'course_ids' => $activeCourses->pluck('course.id')->toArray() ]); $this->courses = $activeCourses->map(function ($memberCourse) use ($todayName) { $whenData = json_decode($memberCourse->course->when, true); Log::debug('Processing course schedule', [ 'member_course_id' => $memberCourse->id, 'course_id' => $memberCourse->course->id, 'course_name' => $memberCourse->course->name, '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, 'course_id' => $memberCourse->course->id ]); break; } } } if (!$todaySchedule) { Log::debug('No matching schedule found for today', [ 'course_id' => $memberCourse->course->id, 'when_data' => $whenData ]); return null; } $days = implode('-', array_map('ucfirst', $todaySchedule['day'])); $course = $memberCourse->course; $courseName = $course->name ?? 'Corso Sconosciuto'; $levelName = $course->level?->name ?? ''; $frequencyName = $course->frequency?->name ?? ''; $typeName = $course->getFormattedTypeField() ?? ''; $courseNameParts = [$courseName]; if ($levelName) $courseNameParts[] = $levelName; if ($typeName) $courseNameParts[] = $typeName; if ($frequencyName) $courseNameParts[] = $frequencyName; $fullCourseName = implode(' - ', $courseNameParts); return [ 'time' => $todaySchedule['from'] . ' - ' . $todaySchedule['to'], 'course_name' => $courseName, 'full_name' => $fullCourseName, 'level_name' => $levelName, 'type_name' => $typeName, 'frequency_name' => $frequencyName, 'days' => $days, 'type' => $course->type ?? 'Standard', 'from_time' => $todaySchedule['from'], 'course_id' => $course->id, 'member_course_id' => $memberCourse->id ]; })->filter()->values(); $sortedCourses = $this->courses->sortBy('from_time')->take(5); Log::info('Courses sorted by time', [ 'sorted_courses' => $sortedCourses->map(function ($course) { return [ 'time' => $course['time'], 'from_time' => $course['from_time'], 'course_name' => $course['course_name'], 'course_id' => $course['course_id'] ]; })->toArray() ]); $this->courses = $sortedCourses->map(function ($course) { unset($course['from_time'], $course['member_course_id'], $course['course_id']); return $course; })->toArray(); $endTime = microtime(true); Log::info('Courses data loaded successfully', [ 'final_courses_count' => count($this->courses), 'execution_time_ms' => round(($endTime - $startTime) * 1000, 2), 'final_courses_display' => $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.level', 'course.frequency']) ->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) { $course = $stat->course; $levelName = is_object($course->level) ? $course->level->name : ''; $frequencyName = is_object($course->frequency) ? $course->frequency->name : ''; return [ 'course_id' => $stat->course_id, 'course_name' => $course->name ?? 'Unknown', 'level_name' => $levelName, 'frequency_name' => $frequencyName, 'participants' => $stat->participants ]; })->toArray() ]); $totalParticipants = $courseStats->sum('participants'); $this->coursesParticipation = $courseStats->map(function ($stat) use ($totalParticipants) { $percentage = $totalParticipants > 0 ? ($stat->participants / $totalParticipants) * 100 : 0; $course = $stat->course; $courseName = $course->name ?? 'Corso Sconosciuto'; $levelName = is_object($course->level) ? $course->level->name : ''; $frequencyName = is_object($course->frequency) ? $course->frequency->name : ''; $typeName = $course->getFormattedTypeField() ?? ''; // Build display name with level and frequency $displayNameParts = [$courseName]; if ($levelName) $displayNameParts[] = $levelName; if ($typeName) $displayNameParts[] = $typeName; if ($frequencyName) $displayNameParts[] = $frequencyName; $displayName = implode(' - ', $displayNameParts); // Assegna colori basati sul nome del corso $color = $this->getCourseColor($courseName); return [ 'course_name' => $displayName, 'base_course_name' => $courseName, 'level_name' => $levelName, 'type_name' => $typeName, 'frequency_name' => $frequencyName, '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 getCourseColor($courseName) { $colors = [ 'padel', 'tennis', 'pallavolo', 'yoga', 'blue', 'pink', 'green', 'red', 'indigo', 'amber', 'cyan', 'lime' ]; $hash = crc32($courseName); $colorIndex = abs($hash) % count($colors); $assignedColor = $colors[$colorIndex]; Log::debug('Course color assigned', [ 'course_name' => $courseName, 'hash' => $hash, 'color_index' => $colorIndex, 'assigned_color' => $assignedColor ]); return $assignedColor; } private function loadSavedNotes() { Log::info('Loading saved notes'); try { $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 { 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()->timezone('Europe/Rome')->format('d/m/Y H:i'), 'completed' => false ]; array_unshift($this->savedNotes, $newNote); $this->saveSavedNotes(); $this->notes = ''; $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'); } } 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]); try { $initialCount = count($this->savedNotes); $this->savedNotes = array_filter($this->savedNotes, function ($note) use ($noteId) { return $note['id'] !== $noteId; }); $this->savedNotes = array_values($this->savedNotes); $finalCount = count($this->savedNotes); if ($initialCount > $finalCount) { $this->saveSavedNotes(); $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() ]); } } 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'); } public function debugCourses() { Log::info('=== DEBUG COURSES CALLED ==='); $today = now()->format('N'); $dayNames = [ 1 => 'lun', 2 => 'mar', 3 => 'mer', 4 => 'gio', 5 => 'ven', 6 => 'sab', 7 => 'dom' ]; $todayName = $dayNames[$today]; // Get all member courses $allCourses = \App\Models\MemberCourse::with('course')->get(); Log::info('All courses debug', [ 'total_courses' => $allCourses->count(), 'today_name' => $todayName, 'courses' => $allCourses->map(function ($mc) { return [ 'id' => $mc->id, 'status' => $mc->status, 'when' => $mc->when, 'course_name' => $mc->course->name ?? 'Unknown' ]; })->toArray() ]); $this->dispatchBrowserEvent('debug-completed'); } public function activateTestCourses() { try { $updated = \App\Models\MemberCourse::whereIn('id', [21, 22, 23, 24]) ->update(['status' => 1]); Log::info('Activated test courses', ['updated_count' => $updated]); $this->loadCoursesData(); $this->loadCoursesParticipation(); $this->dispatchBrowserEvent('courses-activated', [ 'message' => "Attivati $updated corsi per test" ]); } catch (\Exception $e) { Log::error('Error activating courses', ['error' => $e->getMessage()]); } } 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; } }