| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273 | 
							- <?php
 - 
 - namespace App\Support;
 - 
 - use App\Enums\Accounting\DayOfMonth;
 - use App\Enums\Accounting\DayOfWeek;
 - use App\Enums\Accounting\Frequency;
 - use App\Enums\Accounting\IntervalType;
 - use App\Enums\Accounting\Month;
 - use Carbon\CarbonImmutable;
 - use Filament\Forms\Get;
 - use Filament\Forms\Set;
 - use Illuminate\Support\Carbon;
 - 
 - class ScheduleHandler
 - {
 -     protected CarbonImmutable $today;
 - 
 -     protected Set $set;
 - 
 -     protected ?Get $get;
 - 
 -     public function __construct(Set $set, ?Get $get = null)
 -     {
 -         $this->today = today()->toImmutable();
 -         $this->set = $set;
 -         $this->get = $get;
 -     }
 - 
 -     protected function setMany(Set $set, array $values): void
 -     {
 -         foreach ($values as $key => $value) {
 -             $set($key, $value);
 -         }
 -     }
 - 
 -     public function handleFrequencyChange(mixed $state): void
 -     {
 -         $frequency = Frequency::parse($state);
 - 
 -         match (true) {
 -             $frequency->isDaily() => $this->handleDaily(),
 -             $frequency->isWeekly() => $this->handleWeekly(),
 -             $frequency->isMonthly() => $this->handleMonthly(),
 -             $frequency->isYearly() => $this->handleYearly(),
 -             $frequency->isCustom() => $this->handleCustom(),
 -             default => null,
 -         };
 -     }
 - 
 -     public function handleIntervalTypeChange(mixed $state): void
 -     {
 -         $intervalType = IntervalType::parse($state);
 - 
 -         match (true) {
 -             $intervalType->isWeek() => $this->handleWeeklyInterval(),
 -             $intervalType->isMonth() => $this->handleMonthlyInterval(),
 -             $intervalType->isYear() => $this->handleYearlyInterval(),
 -             default => null,
 -         };
 -     }
 - 
 -     public function handleDateChange(?string $component, mixed $state): void
 -     {
 -         match ($component) {
 -             'start_date' => $this->syncComponentsToStartDate(Carbon::parse($state)),
 -             'month' => $this->handleMonthChange($state),
 -             'day_of_month' => $this->handleDayOfMonthChange($state),
 -             'day_of_week' => $this->handleDayOfWeekChange($state),
 -             default => null,
 -         };
 -     }
 - 
 -     protected function handleDaily(): void
 -     {
 -         $this->setMany($this->set, [
 -             'interval_value' => null,
 -             'interval_type' => null,
 -             'day_of_month' => null,
 -             'start_date' => $this->today,
 -         ]);
 -     }
 - 
 -     protected function handleWeekly(): void
 -     {
 -         $currentDayOfWeek = DayOfWeek::parse($this->today->dayOfWeek);
 - 
 -         $this->setMany($this->set, [
 -             'day_of_week' => $currentDayOfWeek,
 -             'start_date' => $this->today,
 -             'interval_value' => null,
 -             'interval_type' => null,
 -             'day_of_month' => null,
 -         ]);
 -     }
 - 
 -     protected function handleMonthly(): void
 -     {
 -         $dayOfMonth = DayOfMonth::First;
 -         $date = $dayOfMonth->resolveDate($this->today);
 - 
 -         $adjustedStartDate = $date->lt($this->today)
 -             ? $dayOfMonth->resolveDate($date->addMonth())
 -             : $dayOfMonth->resolveDate($date);
 - 
 -         $this->setMany($this->set, [
 -             'month' => null,
 -             'day_of_month' => $dayOfMonth,
 -             'start_date' => $adjustedStartDate,
 -             'interval_value' => null,
 -             'interval_type' => null,
 -         ]);
 -     }
 - 
 -     protected function handleYearly(): void
 -     {
 -         $currentMonth = Month::parse($this->today->month);
 -         $currentDayOfMonth = DayOfMonth::parse($this->today->day);
 - 
 -         $this->setMany($this->set, [
 -             'month' => $currentMonth,
 -             'day_of_month' => $currentDayOfMonth,
 -             'start_date' => $this->today,
 -             'interval_value' => null,
 -             'interval_type' => null,
 -         ]);
 -     }
 - 
 -     protected function handleCustom(): void
 -     {
 -         $dayOfMonth = DayOfMonth::First;
 -         $date = $dayOfMonth->resolveDate($this->today);
 - 
 -         $adjustedStartDate = $date->lt($this->today)
 -             ? $dayOfMonth->resolveDate($date->addMonth())
 -             : $dayOfMonth->resolveDate($date);
 - 
 -         $this->setMany($this->set, [
 -             'interval_value' => 1,
 -             'interval_type' => IntervalType::Month,
 -             'month' => null,
 -             'day_of_month' => $dayOfMonth,
 -             'start_date' => $adjustedStartDate,
 -         ]);
 -     }
 - 
 -     protected function handleWeeklyInterval(): void
 -     {
 -         $currentDayOfWeek = DayOfWeek::parse($this->today->dayOfWeek);
 - 
 -         $this->setMany($this->set, [
 -             'day_of_week' => $currentDayOfWeek,
 -             'start_date' => $this->today,
 -         ]);
 -     }
 - 
 -     protected function handleMonthlyInterval(): void
 -     {
 -         $dayOfMonth = DayOfMonth::First;
 -         $date = $dayOfMonth->resolveDate($this->today);
 - 
 -         $adjustedStartDate = $date->lt($this->today)
 -             ? $dayOfMonth->resolveDate($date->addMonth())
 -             : $dayOfMonth->resolveDate($date);
 - 
 -         $this->setMany($this->set, [
 -             'month' => null,
 -             'day_of_month' => $dayOfMonth,
 -             'start_date' => $adjustedStartDate,
 -         ]);
 -     }
 - 
 -     protected function handleYearlyInterval(): void
 -     {
 -         $currentMonth = Month::parse($this->today->month);
 -         $currentDayOfMonth = DayOfMonth::parse($this->today->day);
 - 
 -         $this->setMany($this->set, [
 -             'month' => $currentMonth,
 -             'day_of_month' => $currentDayOfMonth,
 -             'start_date' => $this->today,
 -         ]);
 -     }
 - 
 -     protected function syncComponentsToStartDate(Carbon $startDate): void
 -     {
 -         $frequency = Frequency::parse(($this->get)('frequency'));
 -         $intervalType = IntervalType::parse(($this->get)('interval_type'));
 - 
 -         if ($frequency->isWeekly() || $intervalType?->isWeek()) {
 -             ($this->set)('day_of_week', DayOfWeek::parse($startDate->dayOfWeek));
 -         }
 - 
 -         if ($frequency->isMonthly() || $intervalType?->isMonth() ||
 -             $frequency->isYearly() || $intervalType?->isYear()) {
 -             ($this->set)('day_of_month', $startDate->day);
 -         }
 - 
 -         if ($frequency->isYearly() || $intervalType?->isYear()) {
 -             ($this->set)('month', Month::parse($startDate->month));
 -         }
 -     }
 - 
 -     protected function handleMonthChange(mixed $state): void
 -     {
 -         if (! $this->get) {
 -             return;
 -         }
 - 
 -         $dayOfMonth = DayOfMonth::parse(($this->get)('day_of_month'));
 -         $frequency = Frequency::parse(($this->get)('frequency'));
 -         $intervalType = IntervalType::parse(($this->get)('interval_type'));
 -         $month = Month::parse($state);
 - 
 -         if (($frequency->isYearly() || $intervalType?->isYear()) && $month && $dayOfMonth) {
 -             $date = $dayOfMonth->resolveDate($this->today->month($month->value));
 - 
 -             $adjustedStartDate = $date->lt($this->today)
 -                 ? $dayOfMonth->resolveDate($date->addYear()->month($month->value))
 -                 : $dayOfMonth->resolveDate($date->month($month->value));
 - 
 -             $adjustedDay = min($dayOfMonth->value, $adjustedStartDate->daysInMonth);
 - 
 -             $this->setMany($this->set, [
 -                 'day_of_month' => $adjustedDay,
 -                 'start_date' => $adjustedStartDate,
 -             ]);
 -         }
 -     }
 - 
 -     protected function handleDayOfMonthChange(mixed $state): void
 -     {
 -         if (! $this->get) {
 -             return;
 -         }
 - 
 -         $dayOfMonth = DayOfMonth::parse($state);
 -         $frequency = Frequency::parse(($this->get)('frequency'));
 -         $intervalType = IntervalType::parse(($this->get)('interval_type'));
 -         $month = Month::parse(($this->get)('month'));
 - 
 -         if (($frequency->isMonthly() || $intervalType?->isMonth()) && $dayOfMonth) {
 -             $date = $dayOfMonth->resolveDate($this->today);
 - 
 -             $adjustedStartDate = $date->lt($this->today)
 -                 ? $dayOfMonth->resolveDate($date->addMonth())
 -                 : $dayOfMonth->resolveDate($date);
 - 
 -             ($this->set)('start_date', $adjustedStartDate);
 -         }
 - 
 -         if (($frequency->isYearly() || $intervalType?->isYear()) && $month && $dayOfMonth) {
 -             $date = $dayOfMonth->resolveDate($this->today->month($month->value));
 - 
 -             $adjustedStartDate = $date->lt($this->today)
 -                 ? $dayOfMonth->resolveDate($date->addYear()->month($month->value))
 -                 : $dayOfMonth->resolveDate($date->month($month->value));
 - 
 -             ($this->set)('start_date', $adjustedStartDate);
 -         }
 -     }
 - 
 -     protected function handleDayOfWeekChange(mixed $state): void
 -     {
 -         $dayOfWeek = DayOfWeek::parse($state);
 - 
 -         $adjustedStartDate = $this->today->is($dayOfWeek->name)
 -             ? $this->today
 -             : $this->today->next($dayOfWeek->name);
 - 
 -         ($this->set)('start_date', $adjustedStartDate);
 -     }
 - }
 
 
  |