| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703 |
- <?php
- 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;
- public $totTodayOut = 0;
- public $dayName;
- public $in;
- 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();
- 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');
- 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';
- }
- $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 ($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');
- $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 getCourseColor($courseName)
- {
- $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');
- }
- } 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);
- // 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;
- }
- }
|