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);
- }
- }
|