diff --git a/docs/content/2.essentials/1.configuration.md b/docs/content/2.essentials/1.configuration.md index 465923c7..1141817d 100644 --- a/docs/content/2.essentials/1.configuration.md +++ b/docs/content/2.essentials/1.configuration.md @@ -28,6 +28,54 @@ class AppServiceProvider extends ServiceProvider } ``` +## Date Display Formats + +By default, date and date-time fields use different formats depending on context (forms use `Y-m-d`, tables use `M j, Y`, etc.). You can set a single consistent format across all Filament components. + +### Via Plugin (recommended) + +```php +use Relaticle\CustomFields\CustomFieldsPlugin; + +CustomFieldsPlugin::make() + ->dateDisplayFormat('m/d/Y') + ->dateTimeDisplayFormat('m/d/Y h:i A') +``` + +### Via Facade + +```php +use Relaticle\CustomFields\CustomFields; + +class AppServiceProvider extends ServiceProvider +{ + public function boot() + { + CustomFields::useDateDisplayFormat('m/d/Y'); + CustomFields::useDateTimeDisplayFormat('m/d/Y h:i A'); + } +} +``` + +The configured format applies to: + +| Component | Without config | With config | +|-----------|---------------|-------------| +| Form date pickers | `Y-m-d` / `Y-m-d H:i:s` | Your format | +| Table columns | `M j, Y` / `M j, Y H:i` | Your format | +| Infolist entries | `Y-m-d` / `Y-m-d H:i:s` | Your format | +| Validation messages | `M j, Y` | Your format | + +::alert{type="info"} +This only affects how dates are **displayed**. Storage formats (`Y-m-d` and `Y-m-d H:i:s`) remain unchanged. +:: + +Pass `null` to reset back to component defaults: + +```php +CustomFields::useDateDisplayFormat(null); +``` + ## Configuration File The configuration file (`config/custom-fields.php`) allows you to customize all aspects of the Custom Fields package. It uses modern fluent configurators for type safety and better IDE support. diff --git a/src/CustomFields.php b/src/CustomFields.php index 54105724..6d625846 100644 --- a/src/CustomFields.php +++ b/src/CustomFields.php @@ -33,6 +33,20 @@ final class CustomFields */ public static string $sectionModel = CustomFieldSection::class; + /** + * The display format for date fields (e.g., 'm/d/Y', 'Y-m-d', 'd.m.Y'). + * + * When null, each component uses its own default format. + */ + public static ?string $dateDisplayFormat = null; + + /** + * The display format for date-time fields (e.g., 'm/d/Y h:i A', 'Y-m-d H:i:s'). + * + * When null, each component uses its own default format. + */ + public static ?string $dateTimeDisplayFormat = null; + /** * Get the name of the custom field model used by the application. * @@ -160,6 +174,58 @@ public static function useSectionModel(string $model): static return new self; } + /** + * Set the display format for date custom fields. + * + * This format is used across all Filament components (forms, tables, infolists) + * when rendering date custom field values. + * + * Example: + * ``` + * CustomFields::useDateDisplayFormat('m/d/Y'); + * ``` + */ + public static function useDateDisplayFormat(?string $format): static + { + self::$dateDisplayFormat = $format; + + return new self; + } + + /** + * Set the display format for date-time custom fields. + * + * This format is used across all Filament components (forms, tables, infolists) + * when rendering date-time custom field values. + * + * Example: + * ``` + * CustomFields::useDateTimeDisplayFormat('m/d/Y h:i A'); + * ``` + */ + public static function useDateTimeDisplayFormat(?string $format): static + { + self::$dateTimeDisplayFormat = $format; + + return new self; + } + + /** + * Get the configured date display format, or null for component defaults. + */ + public static function dateDisplayFormat(): ?string + { + return self::$dateDisplayFormat; + } + + /** + * Get the configured date-time display format, or null for component defaults. + */ + public static function dateTimeDisplayFormat(): ?string + { + return self::$dateTimeDisplayFormat; + } + /** * Register a custom tenant resolver callback. * diff --git a/src/CustomFieldsPlugin.php b/src/CustomFieldsPlugin.php index a9f8b2a8..5815eea3 100644 --- a/src/CustomFieldsPlugin.php +++ b/src/CustomFieldsPlugin.php @@ -22,6 +22,10 @@ class CustomFieldsPlugin implements Plugin protected bool|Closure $authorizeUsing = true; + protected ?string $dateDisplayFormat = null; + + protected ?string $dateTimeDisplayFormat = null; + public function getId(): string { return 'custom-fields'; @@ -38,6 +42,14 @@ public function register(Panel $panel): void public function boot(Panel $panel): void { + if ($this->dateDisplayFormat !== null) { + CustomFields::useDateDisplayFormat($this->dateDisplayFormat); + } + + if ($this->dateTimeDisplayFormat !== null) { + CustomFields::useDateTimeDisplayFormat($this->dateTimeDisplayFormat); + } + if (FeatureManager::isEnabled(CustomFieldsFeature::SYSTEM_MULTI_TENANCY)) { Action::configureUsing( fn (Action $action): Action => $action->before( @@ -82,4 +94,18 @@ public function isAuthorized(): bool { return $this->evaluate($this->authorizeUsing) === true; } + + public function dateDisplayFormat(?string $format): static + { + $this->dateDisplayFormat = $format; + + return $this; + } + + public function dateTimeDisplayFormat(?string $format): static + { + $this->dateTimeDisplayFormat = $format; + + return $this; + } } diff --git a/src/Filament/Integration/Components/Forms/DateComponent.php b/src/Filament/Integration/Components/Forms/DateComponent.php index 96b6da80..df12a258 100644 --- a/src/Filament/Integration/Components/Forms/DateComponent.php +++ b/src/Filament/Integration/Components/Forms/DateComponent.php @@ -4,7 +4,9 @@ namespace Relaticle\CustomFields\Filament\Integration\Components\Forms; +use Carbon\Carbon; use Filament\Forms\Components\DatePicker; +use Relaticle\CustomFields\CustomFields; use Relaticle\CustomFields\Filament\Integration\Base\AbstractFormComponent; use Relaticle\CustomFields\Models\CustomField; @@ -12,10 +14,12 @@ { public function create(CustomField $customField): DatePicker { + $configuredFormat = CustomFields::dateDisplayFormat(); + return DatePicker::make($customField->getFieldName()) ->native(false) ->format('Y-m-d') - ->displayFormat('Y-m-d') - ->placeholder('YYYY-MM-DD'); + ->displayFormat($configuredFormat ?? 'Y-m-d') + ->placeholder($configuredFormat ? Carbon::now()->format($configuredFormat) : 'YYYY-MM-DD'); } } diff --git a/src/Filament/Integration/Components/Forms/DateTimeComponent.php b/src/Filament/Integration/Components/Forms/DateTimeComponent.php index 65639059..d37afae9 100644 --- a/src/Filament/Integration/Components/Forms/DateTimeComponent.php +++ b/src/Filament/Integration/Components/Forms/DateTimeComponent.php @@ -4,7 +4,9 @@ namespace Relaticle\CustomFields\Filament\Integration\Components\Forms; +use Carbon\Carbon; use Filament\Forms\Components\DateTimePicker; +use Relaticle\CustomFields\CustomFields; use Relaticle\CustomFields\Filament\Integration\Base\AbstractFormComponent; use Relaticle\CustomFields\Models\CustomField; @@ -12,10 +14,12 @@ { public function create(CustomField $customField): DateTimePicker { + $configuredFormat = CustomFields::dateTimeDisplayFormat(); + return DateTimePicker::make($customField->getFieldName()) ->native(false) ->format('Y-m-d H:i:s') - ->displayFormat('Y-m-d H:i:s') - ->placeholder('YYYY-MM-DD HH:MM:SS'); + ->displayFormat($configuredFormat ?? 'Y-m-d H:i:s') + ->placeholder($configuredFormat ? Carbon::now()->format($configuredFormat) : 'YYYY-MM-DD HH:MM:SS'); } } diff --git a/src/Filament/Integration/Components/Infolists/DateTimeEntry.php b/src/Filament/Integration/Components/Infolists/DateTimeEntry.php index 953ccbe7..db2003b3 100644 --- a/src/Filament/Integration/Components/Infolists/DateTimeEntry.php +++ b/src/Filament/Integration/Components/Infolists/DateTimeEntry.php @@ -5,6 +5,7 @@ namespace Relaticle\CustomFields\Filament\Integration\Components\Infolists; use Filament\Infolists\Components\TextEntry; +use Relaticle\CustomFields\CustomFields; use Relaticle\CustomFields\Filament\Integration\Base\AbstractInfolistEntry; use Relaticle\CustomFields\Models\CustomField; @@ -12,9 +13,20 @@ final class DateTimeEntry extends AbstractInfolistEntry { public function make(CustomField $customField): TextEntry { - return TextEntry::make($customField->getFieldName()) - ->dateTime('Y-m-d H:i:s') - ->placeholder('Y-m-d H:i:s') + $isDateTime = $customField->isDateTimeField(); + + $format = $isDateTime + ? (CustomFields::dateTimeDisplayFormat() ?? 'Y-m-d H:i:s') + : (CustomFields::dateDisplayFormat() ?? 'Y-m-d'); + + $entry = TextEntry::make($customField->getFieldName()) + ->placeholder($format); + + $isDateTime + ? $entry->dateTime($format) + : $entry->date($format); + + return $entry ->label($customField->name) ->state(fn (mixed $record) => $record->getCustomFieldValue($customField)); } diff --git a/src/Filament/Integration/Components/Tables/Columns/DateTimeColumn.php b/src/Filament/Integration/Components/Tables/Columns/DateTimeColumn.php index e1f2d143..0b5d829b 100644 --- a/src/Filament/Integration/Components/Tables/Columns/DateTimeColumn.php +++ b/src/Filament/Integration/Components/Tables/Columns/DateTimeColumn.php @@ -7,6 +7,7 @@ use Closure; use Filament\Tables\Columns\Column as BaseColumn; use Filament\Tables\Columns\TextColumn as BaseTextColumn; +use Relaticle\CustomFields\CustomFields; use Relaticle\CustomFields\Filament\Integration\Base\AbstractTableColumn; use Relaticle\CustomFields\Filament\Integration\Concerns\Tables\ConfiguresColumnLabel; use Relaticle\CustomFields\Filament\Integration\Concerns\Tables\ConfiguresSearchable; @@ -36,12 +37,16 @@ public function make(CustomField $customField): BaseColumn $value = $this->locale->call($this, $value); } - if ($value && $customField->type === 'date_time') { - return $value->format('M j, Y H:i'); + if ($value && $customField->isDateTimeField()) { + $format = CustomFields::dateTimeDisplayFormat() ?? 'M j, Y H:i'; + + return $value->format($format); } - if ($value && $customField->type === 'date') { - return $value->format('M j, Y'); + if ($value && $customField->isDateField()) { + $format = CustomFields::dateDisplayFormat() ?? 'M j, Y'; + + return $value->format($format); } return $value; diff --git a/src/Validation/Rules/DateConstraintRule.php b/src/Validation/Rules/DateConstraintRule.php index 515ef363..564e9bd7 100644 --- a/src/Validation/Rules/DateConstraintRule.php +++ b/src/Validation/Rules/DateConstraintRule.php @@ -8,6 +8,7 @@ use Closure; use Illuminate\Contracts\Validation\ValidationRule; use Illuminate\Database\Eloquent\Model; +use Relaticle\CustomFields\CustomFields; use Relaticle\CustomFields\Data\DateConstraintValue; final readonly class DateConstraintRule implements ValidationRule @@ -49,7 +50,7 @@ public function validate(string $attribute, mixed $value, Closure $fail): void private function getMessage(Carbon $boundary): string { - $formattedDate = $boundary->format('M j, Y'); + $formattedDate = $boundary->format(CustomFields::dateDisplayFormat() ?? 'M j, Y'); return match ($this->comparison) { 'after_or_equal' => sprintf('The :attribute must be on or after %s.', $formattedDate),