Dashboard.php 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818
  1. <?php
  2. namespace App\Http\Livewire;
  3. use Livewire\Component;
  4. use Carbon\Carbon;
  5. use Illuminate\Support\Facades\Log;
  6. class Dashboard extends Component
  7. {
  8. // Existing properties
  9. public $totMembers = 0;
  10. public $totSuppliers = 0;
  11. public $totTodayIn = 0;
  12. public $totTodayOut = 0;
  13. public $dayName;
  14. public $in;
  15. public $out;
  16. public $members;
  17. public $activeUsers = 0;
  18. public $registeredUsers = 0;
  19. public $expiredCertificates = 0;
  20. public $suspendedSubscriptions = 0;
  21. public $activeUsersChange = 0;
  22. public $registeredUsersChange = 0;
  23. public $expiredCertificatesChange = 0;
  24. public $suspendedSubscriptionsChange = 0;
  25. public $toReceive = 0;
  26. public $toPay = 0;
  27. public $courses = [];
  28. public $fields = [];
  29. public $recentUsers = [];
  30. public $recentTransactions = [];
  31. public $coursesParticipation = [];
  32. public $notes = '';
  33. public $savedNotes = [];
  34. public array $membersDatas = [];
  35. public array $recordDatas = [];
  36. public array $labels = [];
  37. public array $monthlyLabels = [];
  38. public array $monthlyIncomeData = [];
  39. public array $monthlyExpenseData = [];
  40. public function render()
  41. {
  42. Log::info('Dashboard render method called');
  43. return view('livewire.dashboard');
  44. }
  45. public function mount()
  46. {
  47. Log::info('Dashboard mount started');
  48. $startTime = microtime(true);
  49. $this->dayName = Carbon::now()->locale('it_IT')->dayName;
  50. Log::info('Day name set', ['day' => $this->dayName]);
  51. $this->loadBasicStats();
  52. $this->loadUserStats();
  53. $this->loadFinancialStats();
  54. $this->loadRecentData();
  55. $this->loadSavedNotes();
  56. $endTime = microtime(true);
  57. $executionTime = round(($endTime - $startTime) * 1000, 2);
  58. Log::info('Dashboard mount completed', [
  59. 'execution_time_ms' => $executionTime,
  60. 'active_users' => $this->activeUsers,
  61. 'courses_count' => count($this->courses),
  62. 'participation_count' => count($this->coursesParticipation)
  63. ]);
  64. }
  65. private function loadBasicStats()
  66. {
  67. Log::info('Loading basic stats');
  68. $startTime = microtime(true);
  69. try {
  70. $this->totMembers = \App\Models\Member::count();
  71. $this->totSuppliers = \App\Models\Supplier::count();
  72. Log::info('Basic counts loaded', [
  73. 'total_members' => $this->totMembers,
  74. 'total_suppliers' => $this->totSuppliers
  75. ]);
  76. // Calculate today's income and expenses
  77. $this->totTodayIn = 0;
  78. $todayRecordsIn = \App\Models\Record::where('type', 'IN')
  79. ->where('date', date("Y-m-d"))
  80. ->get();
  81. foreach ($todayRecordsIn as $record) {
  82. foreach ($record->rows as $row) {
  83. $this->totTodayIn += $row->amount;
  84. }
  85. }
  86. $this->totTodayOut = 0;
  87. $todayRecordsOut = \App\Models\Record::where('type', 'OUT')
  88. ->where('date', date("Y-m-d"))
  89. ->get();
  90. foreach ($todayRecordsOut as $record) {
  91. foreach ($record->rows as $row) {
  92. $this->totTodayOut += $row->amount;
  93. }
  94. }
  95. $endTime = microtime(true);
  96. Log::info('Basic stats loaded successfully', [
  97. 'today_income' => $this->totTodayIn,
  98. 'today_expenses' => $this->totTodayOut,
  99. 'execution_time_ms' => round(($endTime - $startTime) * 1000, 2)
  100. ]);
  101. } catch (\Exception $e) {
  102. Log::error('Error loading basic stats', [
  103. 'error' => $e->getMessage(),
  104. 'file' => $e->getFile(),
  105. 'line' => $e->getLine()
  106. ]);
  107. }
  108. }
  109. private function loadUserStats()
  110. {
  111. Log::info('Loading user stats');
  112. $startTime = microtime(true);
  113. try {
  114. $this->activeUsers = \App\Models\Member::where('is_archived', 0)->orWhere('is_archived', NULL)->count();
  115. $this->registeredUsers = \App\Models\Member::where('current_status', 2)->count();
  116. $this->suspendedSubscriptions = \App\Models\Member::where('current_status', 1)->count();
  117. Log::info('User counts loaded', [
  118. 'active_users' => $this->activeUsers,
  119. 'registered_users' => $this->registeredUsers,
  120. 'suspended_subscriptions' => $this->suspendedSubscriptions
  121. ]);
  122. $this->expiredCertificates = \App\Models\Member::whereHas('certificates', function ($query) {
  123. $query->where('expire_date', '<', now());
  124. })->whereDoesntHave('certificates', function ($query) {
  125. $query->where('expire_date', '>=', now());
  126. })->count();
  127. Log::info('Expired certificates count', ['expired_certificates' => $this->expiredCertificates]);
  128. // Calculate changes from last month
  129. $lastMonth = now()->subMonth();
  130. $endOfLastMonth = $lastMonth->copy()->endOfMonth();
  131. $lastMonthActiveUsers = \App\Models\Member::where('is_archived', false)
  132. ->where('created_at', '<=', $endOfLastMonth)
  133. ->count();
  134. $lastMonthRegisteredUsers = \App\Models\Member::where('current_status', 2)
  135. ->where('updated_at', '<=', $endOfLastMonth)
  136. ->count();
  137. $lastMonthSuspendedSubscriptions = \App\Models\Member::where('current_status', 1)
  138. ->where('updated_at', '<=', $endOfLastMonth)
  139. ->count();
  140. $lastMonthExpiredCertificates = \App\Models\Member::whereHas('certificates', function ($query) use ($endOfLastMonth) {
  141. $query->where('expire_date', '<', $endOfLastMonth);
  142. })->whereDoesntHave('certificates', function ($query) use ($endOfLastMonth) {
  143. $query->where('expire_date', '>=', $endOfLastMonth);
  144. })->count();
  145. $this->activeUsersChange = $this->activeUsers - $lastMonthActiveUsers;
  146. $this->registeredUsersChange = $this->registeredUsers - $lastMonthRegisteredUsers;
  147. $this->expiredCertificatesChange = $this->expiredCertificates - $lastMonthExpiredCertificates;
  148. $this->suspendedSubscriptionsChange = $this->suspendedSubscriptions - $lastMonthSuspendedSubscriptions;
  149. $endTime = microtime(true);
  150. Log::info('User stats loaded successfully', [
  151. 'changes' => [
  152. 'active_users' => $this->activeUsersChange,
  153. 'registered_users' => $this->registeredUsersChange,
  154. 'expired_certificates' => $this->expiredCertificatesChange,
  155. 'suspended_subscriptions' => $this->suspendedSubscriptionsChange
  156. ],
  157. 'execution_time_ms' => round(($endTime - $startTime) * 1000, 2)
  158. ]);
  159. } catch (\Exception $e) {
  160. Log::error('Error loading user stats', [
  161. 'error' => $e->getMessage(),
  162. 'file' => $e->getFile(),
  163. 'line' => $e->getLine()
  164. ]);
  165. }
  166. }
  167. private function loadFinancialStats()
  168. {
  169. Log::info('Loading financial stats');
  170. $startTime = microtime(true);
  171. try {
  172. $currentMonth = now()->format('Y-m');
  173. Log::info('Calculating financial stats for month', ['month' => $currentMonth]);
  174. $this->toReceive = \App\Models\Record::where('type', 'IN')
  175. ->whereRaw('DATE_FORMAT(date, "%Y-%m") = ?', [$currentMonth])
  176. ->where(function ($query) {
  177. $query->where('deleted', false)->orWhere('deleted', null);
  178. })
  179. ->sum('amount') ?? 0;
  180. $this->toPay = \App\Models\Record::where('type', 'OUT')
  181. ->whereRaw('DATE_FORMAT(date, "%Y-%m") = ?', [$currentMonth])
  182. ->where(function ($query) {
  183. $query->where('deleted', false)->orWhere('deleted', null);
  184. })
  185. ->sum('amount') ?? 0;
  186. $endTime = microtime(true);
  187. Log::info('Financial stats loaded successfully', [
  188. 'to_receive' => $this->toReceive,
  189. 'to_pay' => $this->toPay,
  190. 'execution_time_ms' => round(($endTime - $startTime) * 1000, 2)
  191. ]);
  192. } catch (\Exception $e) {
  193. Log::error('Error loading financial stats', [
  194. 'error' => $e->getMessage(),
  195. 'file' => $e->getFile(),
  196. 'line' => $e->getLine()
  197. ]);
  198. }
  199. }
  200. private function loadRecentData()
  201. {
  202. Log::info('Loading recent data');
  203. $startTime = microtime(true);
  204. try {
  205. // Load recent users
  206. $recentMembers = \App\Models\Member::where('is_archived', 0)
  207. ->orWhere('is_archived', NULL)
  208. ->orderBy('created_at', 'desc')
  209. ->limit(5)
  210. ->get();
  211. $this->recentUsers = $recentMembers->map(function ($member) {
  212. return [
  213. 'surname' => strtoupper($member->last_name),
  214. 'name' => strtoupper($member->first_name),
  215. 'phone' => $member->phone ?? '',
  216. 'email' => $member->email ?? ''
  217. ];
  218. })->toArray();
  219. Log::info('Recent users loaded', ['count' => count($this->recentUsers)]);
  220. // Load recent transactions
  221. $recentRecords = \App\Models\Record::where('date', '>=', now()->subDays(30))
  222. ->with(['member', 'supplier'])
  223. ->orderBy('date', 'desc')
  224. ->orderBy('created_at', 'desc')
  225. ->limit(10)
  226. ->get();
  227. $this->recentTransactions = $recentRecords->map(function ($record) {
  228. if ($record->type == 'IN') {
  229. $name = $record->member ?
  230. strtoupper($record->member->last_name) . ' ' . strtoupper($record->member->first_name) :
  231. 'MEMBRO SCONOSCIUTO';
  232. } else {
  233. $name = $record->supplier ?
  234. strtoupper($record->supplier->name) :
  235. 'FORNITORE SCONOSCIUTO';
  236. }
  237. $totalAmount = 0;
  238. foreach ($record->rows as $row) {
  239. $totalAmount += $row->amount;
  240. }
  241. return [
  242. 'name' => $name,
  243. 'amount' => $totalAmount,
  244. 'type' => $record->type == 'IN' ? 'ENTRATA' : 'USCITA'
  245. ];
  246. })->toArray();
  247. Log::info('Recent transactions loaded', ['count' => count($this->recentTransactions)]);
  248. $this->loadCoursesData();
  249. $this->loadCoursesParticipation();
  250. $endTime = microtime(true);
  251. Log::info('Recent data loaded successfully', [
  252. 'execution_time_ms' => round(($endTime - $startTime) * 1000, 2)
  253. ]);
  254. } catch (\Exception $e) {
  255. Log::error('Error loading recent data', [
  256. 'error' => $e->getMessage(),
  257. 'file' => $e->getFile(),
  258. 'line' => $e->getLine()
  259. ]);
  260. }
  261. }
  262. private function loadCoursesData()
  263. {
  264. Log::info('Loading courses data');
  265. $startTime = microtime(true);
  266. try {
  267. $today = now()->format('N');
  268. $dayNames = [
  269. 1 => 'lun',
  270. 2 => 'mar',
  271. 3 => 'mer',
  272. 4 => 'gio',
  273. 5 => 'ven',
  274. 6 => 'sab',
  275. 7 => 'dom'
  276. ];
  277. $todayName = $dayNames[$today];
  278. Log::info('Searching courses for today', [
  279. 'today_number' => $today,
  280. 'today_name' => $todayName
  281. ]);
  282. $memberCourses = \App\Models\MemberCourse::with(['course.level', 'course.frequency', 'member'])
  283. ->whereIn('status', [0, 1])
  284. ->whereHas('course', function ($query) {
  285. $query->whereNotNull('when');
  286. })
  287. ->get();
  288. Log::info('Total member courses found', [
  289. 'count' => $memberCourses->count()
  290. ]);
  291. $activeCourses = $memberCourses->filter(function ($memberCourse) use ($todayName) {
  292. try {
  293. $whenData = json_decode($memberCourse->course->when, true);
  294. if (!is_array($whenData)) {
  295. return false;
  296. }
  297. foreach ($whenData as $schedule) {
  298. if (
  299. isset($schedule['day']) &&
  300. is_array($schedule['day']) &&
  301. in_array($todayName, $schedule['day'])
  302. ) {
  303. return true;
  304. }
  305. }
  306. } catch (\Exception $e) {
  307. Log::debug('Error parsing course schedule', [
  308. 'member_course_id' => $memberCourse->id,
  309. 'course_id' => $memberCourse->course->id,
  310. 'when' => $memberCourse->course->when,
  311. 'error' => $e->getMessage()
  312. ]);
  313. }
  314. return false;
  315. });
  316. Log::info('Active courses found for today', [
  317. 'count' => $activeCourses->count(),
  318. 'course_ids' => $activeCourses->pluck('course.id')->toArray()
  319. ]);
  320. $this->courses = $activeCourses->map(function ($memberCourse) use ($todayName) {
  321. $whenData = json_decode($memberCourse->course->when, true);
  322. Log::debug('Processing course schedule', [
  323. 'member_course_id' => $memberCourse->id,
  324. 'course_id' => $memberCourse->course->id,
  325. 'course_name' => $memberCourse->course->name,
  326. 'when_data' => $whenData,
  327. 'looking_for_day' => $todayName
  328. ]);
  329. $todaySchedule = null;
  330. if (is_array($whenData)) {
  331. foreach ($whenData as $schedule) {
  332. if (
  333. isset($schedule['day']) &&
  334. is_array($schedule['day']) &&
  335. in_array($todayName, $schedule['day'])
  336. ) {
  337. $todaySchedule = $schedule;
  338. Log::debug('Found matching schedule', [
  339. 'schedule' => $schedule,
  340. 'course_id' => $memberCourse->course->id
  341. ]);
  342. break;
  343. }
  344. }
  345. }
  346. if (!$todaySchedule) {
  347. Log::debug('No matching schedule found for today', [
  348. 'course_id' => $memberCourse->course->id,
  349. 'when_data' => $whenData
  350. ]);
  351. return null;
  352. }
  353. $days = implode('-', array_map('ucfirst', $todaySchedule['day']));
  354. $course = $memberCourse->course;
  355. $courseName = $course->name ?? 'Corso Sconosciuto';
  356. $levelName = $course->level?->name ?? '';
  357. $frequencyName = $course->frequency?->name ?? '';
  358. $typeName = $course->getFormattedTypeField() ?? '';
  359. $courseNameParts = [$courseName];
  360. if ($levelName) $courseNameParts[] = $levelName;
  361. if ($typeName) $courseNameParts[] = $typeName;
  362. if ($frequencyName) $courseNameParts[] = $frequencyName;
  363. $fullCourseName = implode(' - ', $courseNameParts);
  364. return [
  365. 'time' => $todaySchedule['from'] . ' - ' . $todaySchedule['to'],
  366. 'course_name' => $courseName,
  367. 'full_name' => $fullCourseName,
  368. 'level_name' => $levelName,
  369. 'type_name' => $typeName,
  370. 'frequency_name' => $frequencyName,
  371. 'days' => $days,
  372. 'type' => $course->type ?? 'Standard',
  373. 'from_time' => $todaySchedule['from'],
  374. 'course_id' => $course->id,
  375. 'member_course_id' => $memberCourse->id
  376. ];
  377. })->filter()->values();
  378. $sortedCourses = $this->courses->sortBy('from_time')->take(5);
  379. Log::info('Courses sorted by time', [
  380. 'sorted_courses' => $sortedCourses->map(function ($course) {
  381. return [
  382. 'time' => $course['time'],
  383. 'from_time' => $course['from_time'],
  384. 'course_name' => $course['course_name'],
  385. 'course_id' => $course['course_id']
  386. ];
  387. })->toArray()
  388. ]);
  389. $this->courses = $sortedCourses->map(function ($course) {
  390. unset($course['from_time'], $course['member_course_id'], $course['course_id']);
  391. return $course;
  392. })->toArray();
  393. $endTime = microtime(true);
  394. Log::info('Courses data loaded successfully', [
  395. 'final_courses_count' => count($this->courses),
  396. 'execution_time_ms' => round(($endTime - $startTime) * 1000, 2),
  397. 'final_courses_display' => $this->courses
  398. ]);
  399. } catch (\Exception $e) {
  400. Log::error('Error loading courses data', [
  401. 'error' => $e->getMessage(),
  402. 'file' => $e->getFile(),
  403. 'line' => $e->getLine()
  404. ]);
  405. $this->courses = [];
  406. }
  407. }
  408. private function loadCoursesParticipation()
  409. {
  410. Log::info('Loading courses participation');
  411. $startTime = microtime(true);
  412. try {
  413. // Conta le partecipazioni per corso (include tutti gli status)
  414. $courseStats = \App\Models\MemberCourse::with(['course.level', 'course.frequency'])
  415. ->whereIn('status', [0, 1]) // Include both statuses
  416. ->selectRaw('course_id, COUNT(*) as participants')
  417. ->groupBy('course_id')
  418. ->orderBy('participants', 'desc')
  419. ->limit(4)
  420. ->get();
  421. Log::info('Course participation stats', [
  422. 'courses_found' => $courseStats->count(),
  423. 'stats' => $courseStats->map(function ($stat) {
  424. $course = $stat->course;
  425. $levelName = is_object($course->level) ? $course->level->name : '';
  426. $frequencyName = is_object($course->frequency) ? $course->frequency->name : '';
  427. return [
  428. 'course_id' => $stat->course_id,
  429. 'course_name' => $course->name ?? 'Unknown',
  430. 'level_name' => $levelName,
  431. 'frequency_name' => $frequencyName,
  432. 'participants' => $stat->participants
  433. ];
  434. })->toArray()
  435. ]);
  436. $totalParticipants = $courseStats->sum('participants');
  437. $this->coursesParticipation = $courseStats->map(function ($stat) use ($totalParticipants) {
  438. $percentage = $totalParticipants > 0 ? ($stat->participants / $totalParticipants) * 100 : 0;
  439. $course = $stat->course;
  440. $courseName = $course->name ?? 'Corso Sconosciuto';
  441. $levelName = is_object($course->level) ? $course->level->name : '';
  442. $frequencyName = is_object($course->frequency) ? $course->frequency->name : '';
  443. $typeName = $course->getFormattedTypeField() ?? '';
  444. // Build display name with level and frequency
  445. $displayNameParts = [$courseName];
  446. if ($levelName) $displayNameParts[] = $levelName;
  447. if ($typeName) $displayNameParts[] = $typeName;
  448. if ($frequencyName) $displayNameParts[] = $frequencyName;
  449. $displayName = implode(' - ', $displayNameParts);
  450. // Assegna colori basati sul nome del corso
  451. $color = $this->getCourseColor($courseName);
  452. return [
  453. 'course_name' => $displayName,
  454. 'base_course_name' => $courseName,
  455. 'level_name' => $levelName,
  456. 'type_name' => $typeName,
  457. 'frequency_name' => $frequencyName,
  458. 'participants' => $stat->participants,
  459. 'percentage' => round($percentage, 1),
  460. 'color' => $color
  461. ];
  462. })->toArray();
  463. $endTime = microtime(true);
  464. Log::info('Courses participation loaded successfully', [
  465. 'total_participants' => $totalParticipants,
  466. 'participation_data' => $this->coursesParticipation,
  467. 'execution_time_ms' => round(($endTime - $startTime) * 1000, 2)
  468. ]);
  469. } catch (\Exception $e) {
  470. Log::error('Error loading courses participation', [
  471. 'error' => $e->getMessage(),
  472. 'file' => $e->getFile(),
  473. 'line' => $e->getLine()
  474. ]);
  475. $this->coursesParticipation = [];
  476. }
  477. }
  478. private function getCourseColor($courseName)
  479. {
  480. $colors = [
  481. 'padel',
  482. 'tennis',
  483. 'pallavolo',
  484. 'yoga',
  485. 'blue',
  486. 'pink',
  487. 'green',
  488. 'red',
  489. 'indigo',
  490. 'amber',
  491. 'cyan',
  492. 'lime'
  493. ];
  494. $hash = crc32($courseName);
  495. $colorIndex = abs($hash) % count($colors);
  496. $assignedColor = $colors[$colorIndex];
  497. Log::debug('Course color assigned', [
  498. 'course_name' => $courseName,
  499. 'hash' => $hash,
  500. 'color_index' => $colorIndex,
  501. 'assigned_color' => $assignedColor
  502. ]);
  503. return $assignedColor;
  504. }
  505. private function loadSavedNotes()
  506. {
  507. Log::info('Loading saved notes');
  508. try {
  509. $this->savedNotes = session()->get('dashboard_notes', []);
  510. Log::info('Saved notes loaded', [
  511. 'notes_count' => count($this->savedNotes)
  512. ]);
  513. } catch (\Exception $e) {
  514. Log::error('Error loading saved notes', [
  515. 'error' => $e->getMessage()
  516. ]);
  517. $this->savedNotes = [];
  518. }
  519. }
  520. private function saveSavedNotes()
  521. {
  522. try {
  523. session()->put('dashboard_notes', $this->savedNotes);
  524. Log::info('Notes saved to session', [
  525. 'notes_count' => count($this->savedNotes)
  526. ]);
  527. } catch (\Exception $e) {
  528. Log::error('Error saving notes', [
  529. 'error' => $e->getMessage()
  530. ]);
  531. }
  532. }
  533. public function saveNote()
  534. {
  535. Log::info('Save note called', ['note_text' => $this->notes]);
  536. try {
  537. if (trim($this->notes) !== '') {
  538. $newNote = [
  539. 'id' => uniqid(),
  540. 'text' => trim($this->notes),
  541. 'created_at' => now()->format('d/m/Y H:i'),
  542. 'completed' => false
  543. ];
  544. array_unshift($this->savedNotes, $newNote);
  545. $this->saveSavedNotes();
  546. $this->notes = '';
  547. $this->dispatchBrowserEvent('note-saved');
  548. Log::info('Note saved successfully', [
  549. 'note_id' => $newNote['id'],
  550. 'total_notes' => count($this->savedNotes)
  551. ]);
  552. } else {
  553. Log::warning('Attempted to save empty note');
  554. }
  555. } catch (\Exception $e) {
  556. Log::error('Error saving note', [
  557. 'error' => $e->getMessage(),
  558. 'file' => $e->getFile(),
  559. 'line' => $e->getLine()
  560. ]);
  561. }
  562. }
  563. public function completeNote($noteId)
  564. {
  565. Log::info('Complete note called', ['note_id' => $noteId]);
  566. try {
  567. $initialCount = count($this->savedNotes);
  568. $this->savedNotes = array_filter($this->savedNotes, function ($note) use ($noteId) {
  569. return $note['id'] !== $noteId;
  570. });
  571. $this->savedNotes = array_values($this->savedNotes);
  572. $finalCount = count($this->savedNotes);
  573. if ($initialCount > $finalCount) {
  574. $this->saveSavedNotes();
  575. $this->dispatchBrowserEvent('note-completed');
  576. Log::info('Note completed successfully', [
  577. 'note_id' => $noteId,
  578. 'remaining_notes' => $finalCount
  579. ]);
  580. } else {
  581. Log::warning('Note not found for completion', ['note_id' => $noteId]);
  582. }
  583. } catch (\Exception $e) {
  584. Log::error('Error completing note', [
  585. 'note_id' => $noteId,
  586. 'error' => $e->getMessage(),
  587. 'file' => $e->getFile(),
  588. 'line' => $e->getLine()
  589. ]);
  590. }
  591. }
  592. public function addMember()
  593. {
  594. Log::info('Redirecting to add member');
  595. return redirect()->to('/members?new=1');
  596. }
  597. public function addSupplier()
  598. {
  599. Log::info('Redirecting to add supplier');
  600. return redirect()->to('/suppliers?new=1');
  601. }
  602. public function addIn()
  603. {
  604. Log::info('Redirecting to add income record');
  605. return redirect()->to('/in?new=1');
  606. }
  607. public function addOut()
  608. {
  609. Log::info('Redirecting to add expense record');
  610. return redirect()->to('/out?new=1');
  611. }
  612. public function debugCourses()
  613. {
  614. Log::info('=== DEBUG COURSES CALLED ===');
  615. $today = now()->format('N');
  616. $dayNames = [
  617. 1 => 'lun',
  618. 2 => 'mar',
  619. 3 => 'mer',
  620. 4 => 'gio',
  621. 5 => 'ven',
  622. 6 => 'sab',
  623. 7 => 'dom'
  624. ];
  625. $todayName = $dayNames[$today];
  626. // Get all member courses
  627. $allCourses = \App\Models\MemberCourse::with('course')->get();
  628. Log::info('All courses debug', [
  629. 'total_courses' => $allCourses->count(),
  630. 'today_name' => $todayName,
  631. 'courses' => $allCourses->map(function ($mc) {
  632. return [
  633. 'id' => $mc->id,
  634. 'status' => $mc->status,
  635. 'when' => $mc->when,
  636. 'course_name' => $mc->course->name ?? 'Unknown'
  637. ];
  638. })->toArray()
  639. ]);
  640. $this->dispatchBrowserEvent('debug-completed');
  641. }
  642. public function activateTestCourses()
  643. {
  644. try {
  645. $updated = \App\Models\MemberCourse::whereIn('id', [21, 22, 23, 24])
  646. ->update(['status' => 1]);
  647. Log::info('Activated test courses', ['updated_count' => $updated]);
  648. $this->loadCoursesData();
  649. $this->loadCoursesParticipation();
  650. $this->dispatchBrowserEvent('courses-activated', [
  651. 'message' => "Attivati $updated corsi per test"
  652. ]);
  653. } catch (\Exception $e) {
  654. Log::error('Error activating courses', ['error' => $e->getMessage()]);
  655. }
  656. }
  657. private function getLabels()
  658. {
  659. $labels = array();
  660. for ($i = 6; $i >= 0; $i--) {
  661. $labels[] = date("d/M", strtotime('-' . $i . ' days'));
  662. }
  663. return $labels;
  664. }
  665. private function getRecordData($type)
  666. {
  667. $data = [];
  668. for ($i = 6; $i >= 0; $i--) {
  669. $found = false;
  670. $records = $type == 'IN' ? $this->in : $this->out;
  671. foreach ($records as $record) {
  672. if (date("Y-m-d", strtotime($record->date)) == date("Y-m-d", strtotime('-' . $i . ' days'))) {
  673. $data[] = $record->total;
  674. $found = true;
  675. break;
  676. }
  677. }
  678. if (!$found) {
  679. $data[] = 0;
  680. }
  681. }
  682. return $data;
  683. }
  684. private function getMemberData()
  685. {
  686. $data = [];
  687. for ($i = 6; $i >= 0; $i--) {
  688. $found = false;
  689. foreach ($this->members as $member) {
  690. if (date("Y-m-d", strtotime($member->created_at)) == date("Y-m-d", strtotime('-' . $i . ' days'))) {
  691. $data[] = $member->total;
  692. $found = true;
  693. break;
  694. }
  695. }
  696. if (!$found) {
  697. $data[] = 0;
  698. }
  699. }
  700. return $data;
  701. }
  702. }