record = AppearanceModel::firstOrNew([ 'company_id' => auth()->user()->currentCompany->id, ]); abort_unless(static::canView($this->record), 404); $this->fillForm(); } public function fillForm(): void { $data = $this->record->attributesToArray(); $data = $this->mutateFormDataBeforeFill($data); $this->form->fill($data); } protected function mutateFormDataBeforeFill(array $data): array { return $data; } protected function mutateFormDataBeforeSave(array $data): array { return $data; } public function save(): void { try { $data = $this->form->getState(); $data = $this->mutateFormDataBeforeSave($data); $this->handleRecordUpdate($this->record, $data); } catch (Halt $exception) { return; } $this->getSavedNotification()?->send(); if ($redirectUrl = $this->getRedirectUrl()) { $this->redirect($redirectUrl); } } protected function getSavedNotification(): ?Notification { $title = $this->getSavedNotificationTitle(); if (blank($title)) { return null; } return Notification::make() ->success() ->title($this->getSavedNotificationTitle()); } protected function getSavedNotificationTitle(): ?string { return __('filament-panels::pages/tenancy/edit-tenant-profile.notifications.saved.title'); } protected function getRedirectUrl(): ?string { return null; } public function form(Form $form): Form { return $form ->schema([ $this->getGeneralSection(), $this->getLayoutSection(), $this->getDataPresentationSection(), ]) ->model($this->record) ->statePath('data') ->operation('edit'); } protected function getGeneralSection(): Component { return Section::make('General') ->schema([ Select::make('primary_color') ->label('Primary Color') ->native(false) ->allowHtml() ->selectablePlaceholder(false) ->rule('required') ->options(collect(PrimaryColor::cases()) ->mapWithKeys(static fn ($case) => [ $case->value => " " . str($case->value)->title() . " " ]), ), Select::make('font') ->label('Font') ->native(false) ->selectablePlaceholder(false) ->rule('required') ->allowHtml() ->options(collect(Font::cases()) ->mapWithKeys(static fn ($case) => [ $case->value => "{$case->getLabel()}" ]), ), ])->columns(); } protected function getLayoutSection(): Component { return Section::make('Layout') ->schema([ Select::make('max_content_width') ->label('Max Content Width') ->native(false) ->selectablePlaceholder(false) ->rule('required') ->options(MaxContentWidth::class), Select::make('modal_width') ->label('Modal Width') ->native(false) ->selectablePlaceholder(false) ->rule('required') ->options(ModalWidth::class), ButtonGroup::make('has_top_navigation') ->label('Navigation Layout') ->boolean('Top Navigation', 'Side Navigation') ->rule('required'), ToggleButton::make('is_table_striped') ->label('Striped Tables') ->onLabel('Enabled') ->offLabel('Disabled') ->rule('required'), ])->columns(); } protected function getDataPresentationSection(): Component { return Section::make('Data Presentation') ->schema([ Select::make('table_sort_direction') ->label('Table Sort Direction') ->native(false) ->selectablePlaceholder(false) ->rule('required') ->options(TableSortDirection::class), Select::make('records_per_page') ->label('Records Per Page') ->native(false) ->selectablePlaceholder(false) ->rule('required') ->options(RecordsPerPage::class), ])->columns(); } protected function handleRecordUpdate(AppearanceModel $record, array $data): AppearanceModel { $record_array = array_map('strval', $record->toArray()); $data_array = array_map('strval', $data); $diff = array_diff_assoc($data_array, $record_array); $keysToWatch = [ 'primary_color', 'max_content_width', 'has_top_navigation', 'font', ]; foreach ($diff as $key => $value) { if (in_array($key, $keysToWatch, true)) { $this->dispatch('appearanceUpdated'); } } // If the primary color or font has changed, we need to update the associated models accent_color column. if (array_key_exists('primary_color', $diff) || array_key_exists('font', $diff)) { $primaryColorToHex = PrimaryColor::from($data['primary_color'])->getHexCode(); $font = Font::from($data['font'])->value; $this->record->company->defaultBill()->update([ 'accent_color' => $primaryColorToHex, 'font' => $font, ]); $this->record->company->defaultInvoice()->update([ 'accent_color' => $primaryColorToHex, 'font' => $font, ]); } $record->update($data); return $record; } /** * @return array */ protected function getFormActions(): array { return [ $this->getSaveFormAction(), ]; } protected function getSaveFormAction(): Action { return Action::make('save') ->label(__('filament-panels::pages/tenancy/edit-tenant-profile.form.actions.save.label')) ->submit('save') ->keyBindings(['mod+s']); } public static function canView(Model $record): bool { try { return authorize('update', $record)->allowed(); } catch (AuthorizationException $exception) { return $exception->toResponse()->allowed(); } } }