diff --git a/packages/forms/src/Components/DateTimePicker.php b/packages/forms/src/Components/DateTimePicker.php index f96deb73d1..bd6a50b423 100644 --- a/packages/forms/src/Components/DateTimePicker.php +++ b/packages/forms/src/Components/DateTimePicker.php @@ -8,6 +8,8 @@ use Carbon\Exceptions\InvalidFormatException; use Closure; use DateTime; use Filament\Schemas\Components\Contracts\HasAffixActions; +use Filament\Schemas\Components\StateCasts\Contracts\StateCast; +use Filament\Schemas\Components\StateCasts\DateTimeStateCast; use Filament\Support\Concerns\HasExtraAlpineAttributes; use Filament\Support\Facades\FilamentTimezone; use Filament\Support\Icons\Heroicon; @@ -84,71 +86,44 @@ class DateTimePicker extends Field implements HasAffixActions { parent::setUp(); - $this->afterStateHydrated(static function (DateTimePicker $component, $state): void { - if (blank($state)) { - return; - } - - if (! $state instanceof CarbonInterface) { - try { - $state = Carbon::createFromFormat($component->getFormat(), (string) $state, config('app.timezone')); - } catch (InvalidFormatException $exception) { - try { - $state = Carbon::parse($state, config('app.timezone')); - } catch (InvalidFormatException $exception) { - $component->state(null); - - return; - } - } - } - - $state = $state->setTimezone($component->getTimezone()); - - if (! $component->isNative()) { - $component->state((string) $state); - - return; - } - - if (! $component->hasTime()) { - $component->state($state->toDateString()); - - return; - } - - $precision = $component->hasSeconds() ? 'second' : 'minute'; - - if (! $component->hasDate()) { - $component->state($state->toTimeString($precision)); - - return; - } - - $component->state($state->toDateTimeString($precision)); - }); - - $this->dehydrateStateUsing(static function (DateTimePicker $component, $state) { - if (blank($state)) { - return null; - } - - if (! $state instanceof CarbonInterface) { - $state = Carbon::parse($state); - } - - $state->shiftTimezone($component->getTimezone()); - $state->setTimezone(config('app.timezone')); - - return $state->format($component->getFormat()); - }); - $this->rule( 'date', static fn (DateTimePicker $component): bool => $component->hasDate(), ); } + /** + * @return array + */ + public function getDefaultStateCasts(): array + { + return [ + ...parent::getDefaultStateCasts(), + app(DateTimeStateCast::class, [ + 'format' => $this->getFormat(), + 'internalFormat' => $this->getInternalFormat(), + 'timezone' => $this->getTimezone(), + ]), + ]; + } + + public function getInternalFormat(): string + { + if (! $this->isNative()) { + return 'Y-m-d H:i:s'; + } + + if (! $this->hasTime()) { + return 'Y-m-d'; + } + + if (! $this->hasDate()) { + return $this->hasSeconds() ? 'H:i:s' : 'H:i'; + } + + return 'Y-m-d H:i:s'; + } + public function displayFormat(string | Closure | null $format): static { $this->displayFormat = $format; diff --git a/packages/forms/src/Components/Select.php b/packages/forms/src/Components/Select.php index d7c5424c35..4554b5fdbf 100644 --- a/packages/forms/src/Components/Select.php +++ b/packages/forms/src/Components/Select.php @@ -1367,21 +1367,6 @@ class Select extends Field implements Contracts\CanDisableOptions, Contracts\Has return (bool) $this->evaluate($this->canOptionLabelsWrap); } - public function hydrateDefaultState(?array &$hydratedDefaultState): void - { - parent::hydrateDefaultState($hydratedDefaultState); - - if (is_bool($state = $this->getState())) { - $state = $state ? 1 : 0; - - $this->state($state); - - if (is_array($hydratedDefaultState)) { - Arr::set($hydratedDefaultState, $this->getStatePath(), $state); /** @phpstan-ignore parameterByRef.type */ - } - } - } - public function getQualifiedRelatedKeyNameForRelationship(Relation $relationship): string { if ($relationship instanceof BelongsToMany) { diff --git a/packages/schemas/src/Components/Concerns/HasState.php b/packages/schemas/src/Components/Concerns/HasState.php index cd6206a526..e94d0e2966 100644 --- a/packages/schemas/src/Components/Concerns/HasState.php +++ b/packages/schemas/src/Components/Concerns/HasState.php @@ -451,14 +451,14 @@ trait HasState } if (! $this->hasDefaultState()) { - $this->hasStatePath() && $this->state(null); + $this->hasStatePath() && $this->rawState(null); return; } $defaultState = $this->getDefaultState(); - $this->state($defaultState); + $this->rawState($defaultState); Arr::set($hydratedDefaultState, $statePath, $defaultState); /** @phpstan-ignore parameterByRef.type */ } diff --git a/packages/schemas/src/Components/StateCasts/DateTimeStateCast.php b/packages/schemas/src/Components/StateCasts/DateTimeStateCast.php new file mode 100644 index 0000000000..98c0254ffa --- /dev/null +++ b/packages/schemas/src/Components/StateCasts/DateTimeStateCast.php @@ -0,0 +1,56 @@ +shiftTimezone($this->timezone); + $state->setTimezone(config('app.timezone')); + + return $state->format($this->format); + } + + public function set(mixed $state): ?string + { + if (blank($state)) { + return null; + } + + if (! $state instanceof CarbonInterface) { + try { + $state = Carbon::createFromFormat($this->format, (string) $state, config('app.timezone')); + } catch (InvalidFormatException) { + try { + $state = Carbon::parse($state, config('app.timezone')); + } catch (InvalidFormatException) { + return null; + } + } + } + + $state = $state->setTimezone($this->timezone); + + return $state->format($this->internalFormat); + } +}