dishplanner/app/Livewire/Schedule/ScheduleCalendar.php

401 lines
12 KiB
PHP
Raw Normal View History

<?php
namespace App\Livewire\Schedule;
use App\Models\Dish;
use App\Models\Schedule;
use App\Models\ScheduledUserDish;
use App\Models\User;
use App\Models\UserDish;
use Carbon\Carbon;
use DishPlanner\Schedule\Services\ScheduleCalendarService;
use DishPlanner\ScheduledUserDish\Actions\DeleteScheduledUserDishForDateAction;
use DishPlanner\ScheduledUserDish\Actions\SkipScheduledUserDishForDateAction;
use Exception;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Facades\Log;
use Livewire\Component;
class ScheduleCalendar extends Component
{
public $currentMonth;
public $currentYear;
public $calendarDays = [];
public $showRegenerateModal = false;
public $regenerateDate = null;
public $regenerateUserId = null;
// Edit dish modal
public $showEditDishModal = false;
public $editDate = null;
public $editUserId = null;
public $selectedDishId = null;
public $availableDishes = [];
// Add dish modal
public $showAddDishModal = false;
public $addDate = null;
public $addUserId = null;
public $addSelectedDishId = null;
public $addAvailableUsers = [];
public $addAvailableDishes = [];
public function mount(): void
{
$this->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->addUserId = null;
$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->addUserId = null;
$this->addSelectedDishId = null;
$this->showAddDishModal = true;
}
public function updatedAddUserId($value): void
{
if ($value) {
// Load dishes available for selected user
$this->addAvailableDishes = Dish::whereHas('users', function ($query) use ($value) {
$query->where('users.id', $value);
})->orderBy('name')->get();
} else {
$this->addAvailableDishes = [];
}
$this->addSelectedDishId = null;
}
public function saveAddDish(): void
{
try {
if (!$this->addUserId) {
session()->flash('error', 'Please select a user.');
return;
}
if (!$this->authorizeUser($this->addUserId)) {
session()->flash('error', 'Unauthorized action.');
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]
);
// Check if user already has a dish scheduled for this date
$existing = ScheduledUserDish::where('schedule_id', $schedule->id)
->where('user_id', $this->addUserId)
->first();
if ($existing) {
session()->flash('error', 'This user already has a dish scheduled for this date. Use Edit instead.');
return;
}
// Find the UserDish for this user and dish
$userDish = UserDish::where('user_id', $this->addUserId)
->where('dish_id', $this->addSelectedDishId)
->first();
if (!$userDish) {
session()->flash('error', 'This dish is not assigned to this user.');
return;
}
// Create the scheduled user dish
ScheduledUserDish::create([
'schedule_id' => $schedule->id,
'user_id' => $this->addUserId,
'user_dish_id' => $userDish->id,
'is_skipped' => false,
]);
$this->showAddDishModal = false;
$this->addDate = null;
$this->addUserId = null;
$this->addSelectedDishId = null;
$this->addAvailableUsers = [];
$this->addAvailableDishes = [];
$this->loadCalendar();
session()->flash('success', 'Dish added successfully!');
} catch (Exception $e) {
Log::error('Add dish failed', ['exception' => $e]);
session()->flash('error', 'Unable to add dish. Please try again.');
}
}
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);
}
}