currentMonth = now()->month; $this->currentYear = now()->year; $this->loadCalendar(); } protected $listeners = ['schedule-generated' => 'refreshCalendar']; public function render(): View { return view('livewire.schedule.schedule-calendar'); } public function refreshCalendar(): void { $this->loadCalendar(); } public function loadCalendar(): void { $service = new ScheduleCalendarService(); $this->calendarDays = $service->getCalendarDays( auth()->user(), $this->currentMonth, $this->currentYear ); } public function previousMonth(): void { if ($this->currentMonth === 1) { $this->currentMonth = 12; $this->currentYear--; } else { $this->currentMonth--; } $this->loadCalendar(); } public function nextMonth(): void { if ($this->currentMonth === 12) { $this->currentMonth = 1; $this->currentYear++; } else { $this->currentMonth++; } $this->loadCalendar(); } public function regenerateForUserDate($date, $userId): void { if (!$this->authorizeUser($userId)) { session()->flash('error', 'Unauthorized action.'); return; } $this->regenerateDate = $date; $this->regenerateUserId = $userId; $this->showRegenerateModal = true; } public function confirmRegenerate(): void { try { if (!$this->authorizeUser($this->regenerateUserId)) { session()->flash('error', 'Unauthorized action.'); return; } $action = new DeleteScheduledUserDishForDateAction(); $action->execute( auth()->user(), Carbon::parse($this->regenerateDate), $this->regenerateUserId ); $this->showRegenerateModal = false; $this->loadCalendar(); session()->flash('success', 'Schedule regenerated for the selected date!'); } catch (Exception $e) { Log::error('Schedule regeneration failed', ['exception' => $e, 'date' => $this->regenerateDate]); session()->flash('error', 'Unable to regenerate schedule. Please try again.'); } } public function skipDay($date, $userId): void { try { if (!$this->authorizeUser($userId)) { session()->flash('error', 'Unauthorized action.'); return; } $action = new SkipScheduledUserDishForDateAction(); $action->execute( auth()->user(), Carbon::parse($date), $userId ); $this->loadCalendar(); session()->flash('success', 'Day skipped successfully!'); } catch (Exception $e) { Log::error('Skip day failed', ['exception' => $e, 'date' => $date, 'userId' => $userId]); session()->flash('error', 'Unable to skip day. Please try again.'); } } private function authorizeUser(int $userId): bool { $user = User::find($userId); return $user && $user->planner_id === auth()->id(); } public function cancel(): void { $this->showRegenerateModal = false; $this->regenerateDate = null; $this->regenerateUserId = null; $this->showEditDishModal = false; $this->editDate = null; $this->editUserId = null; $this->selectedDishId = null; $this->availableDishes = []; $this->showAddDishModal = false; $this->addDate = null; $this->addUserIds = []; $this->addSelectedDishId = null; $this->addAvailableUsers = []; $this->addAvailableDishes = []; } public function removeDish($date, $userId): void { try { if (!$this->authorizeUser($userId)) { session()->flash('error', 'Unauthorized action.'); return; } $schedule = Schedule::where('planner_id', auth()->id()) ->where('date', $date) ->first(); if ($schedule) { ScheduledUserDish::where('schedule_id', $schedule->id) ->where('user_id', $userId) ->delete(); } $this->loadCalendar(); session()->flash('success', 'Dish removed successfully!'); } catch (Exception $e) { Log::error('Remove dish failed', ['exception' => $e, 'date' => $date, 'userId' => $userId]); session()->flash('error', 'Unable to remove dish. Please try again.'); } } public function openAddDishModal($date): void { $this->addDate = $date; // Load all users for this planner $this->addAvailableUsers = User::where('planner_id', auth()->id()) ->orderBy('name') ->get(); $this->addAvailableDishes = []; $this->addUserIds = []; $this->addSelectedDishId = null; $this->showAddDishModal = true; } public function toggleAllUsers(): void { if (count($this->addUserIds) === count($this->addAvailableUsers)) { $this->addUserIds = []; } else { $this->addUserIds = $this->addAvailableUsers->pluck('id')->map(fn($id) => (string) $id)->toArray(); } $this->updateAvailableDishes(); } public function updatedAddUserIds(): void { $this->updateAvailableDishes(); } private function updateAvailableDishes(): void { if (empty($this->addUserIds)) { $this->addAvailableDishes = []; } else { // Load dishes that ALL selected users have in common $selectedCount = count($this->addUserIds); $this->addAvailableDishes = Dish::whereHas('users', function ($query) { $query->whereIn('users.id', $this->addUserIds); }, '=', $selectedCount)->orderBy('name')->get(); } $this->addSelectedDishId = null; } public function saveAddDish(): void { try { if (empty($this->addUserIds)) { session()->flash('error', 'Please select at least one user.'); return; } if (!$this->addSelectedDishId) { session()->flash('error', 'Please select a dish.'); return; } // Find or create the schedule for this date $schedule = Schedule::firstOrCreate( [ 'planner_id' => auth()->id(), 'date' => $this->addDate, ], ['is_skipped' => false] ); $addedCount = 0; $skippedCount = 0; foreach ($this->addUserIds as $userId) { if (!$this->authorizeUser((int) $userId)) { $skippedCount++; continue; } // Check if user already has a dish scheduled for this date $existing = ScheduledUserDish::where('schedule_id', $schedule->id) ->where('user_id', $userId) ->first(); if ($existing) { $skippedCount++; continue; } // Find the UserDish for this user and dish $userDish = UserDish::where('user_id', $userId) ->where('dish_id', $this->addSelectedDishId) ->first(); if (!$userDish) { $skippedCount++; continue; } // Create the scheduled user dish ScheduledUserDish::create([ 'schedule_id' => $schedule->id, 'user_id' => $userId, 'user_dish_id' => $userDish->id, 'is_skipped' => false, ]); $addedCount++; } $this->closeAddDishModal(); $this->loadCalendar(); if ($addedCount > 0 && $skippedCount > 0) { session()->flash('success', "Dish added for {$addedCount} user(s). {$skippedCount} user(s) skipped (already scheduled)."); } elseif ($addedCount > 0) { session()->flash('success', "Dish added for {$addedCount} user(s)!"); } else { session()->flash('error', 'No users could be scheduled. They may already have dishes for this date.'); } } catch (Exception $e) { Log::error('Add dish failed', ['exception' => $e]); session()->flash('error', 'Unable to add dish. Please try again.'); } } private function closeAddDishModal(): void { $this->showAddDishModal = false; $this->addDate = null; $this->addUserIds = []; $this->addSelectedDishId = null; $this->addAvailableUsers = []; $this->addAvailableDishes = []; } public function editDish($date, $userId): void { if (!$this->authorizeUser($userId)) { session()->flash('error', 'Unauthorized action.'); return; } $this->editDate = $date; $this->editUserId = $userId; // Load dishes available for this user (via UserDish pivot) $this->availableDishes = Dish::whereHas('users', function ($query) use ($userId) { $query->where('users.id', $userId); })->orderBy('name')->get(); // Get currently selected dish for this date/user if exists $schedule = Schedule::where('planner_id', auth()->id()) ->where('date', $date) ->first(); if ($schedule) { $scheduledUserDish = ScheduledUserDish::where('schedule_id', $schedule->id) ->where('user_id', $userId) ->first(); if ($scheduledUserDish && $scheduledUserDish->userDish) { $this->selectedDishId = $scheduledUserDish->userDish->dish_id; } } $this->showEditDishModal = true; } public function saveDish(): void { try { if (!$this->authorizeUser($this->editUserId)) { session()->flash('error', 'Unauthorized action.'); return; } if (!$this->selectedDishId) { session()->flash('error', 'Please select a dish.'); return; } // Find or create the schedule for this date $schedule = Schedule::firstOrCreate( [ 'planner_id' => auth()->id(), 'date' => $this->editDate, ], ['is_skipped' => false] ); // Find the UserDish for this user and dish $userDish = UserDish::where('user_id', $this->editUserId) ->where('dish_id', $this->selectedDishId) ->first(); if (!$userDish) { session()->flash('error', 'This dish is not assigned to this user.'); return; } // Update or create the scheduled user dish ScheduledUserDish::updateOrCreate( [ 'schedule_id' => $schedule->id, 'user_id' => $this->editUserId, ], [ 'user_dish_id' => $userDish->id, 'is_skipped' => false, ] ); $this->showEditDishModal = false; $this->editDate = null; $this->editUserId = null; $this->selectedDishId = null; $this->availableDishes = []; $this->loadCalendar(); session()->flash('success', 'Dish updated successfully!'); } catch (Exception $e) { Log::error('Save dish failed', ['exception' => $e]); session()->flash('error', 'Unable to save dish. Please try again.'); } } public function getMonthNameProperty(): string { $service = new ScheduleCalendarService(); return $service->getMonthName($this->currentMonth, $this->currentYear); } }