diff --git a/app/Filament/Admin/Resources/BlogCategories/BlogCategoryResource.php b/app/Filament/Admin/Resources/BlogCategories/BlogCategoryResource.php new file mode 100644 index 0000000..c001d09 --- /dev/null +++ b/app/Filament/Admin/Resources/BlogCategories/BlogCategoryResource.php @@ -0,0 +1,77 @@ + ListBlogCategories::route('/'), + 'create' => CreateBlogCategory::route('/create'), + 'edit' => EditBlogCategory::route('/{record}/edit'), + ]; + } + + public static function getRecordRouteBindingEloquentQuery(): Builder + { + return parent::getRecordRouteBindingEloquentQuery() + ->withoutGlobalScopes([ + SoftDeletingScope::class, + ]); + } +} + diff --git a/app/Filament/Admin/Resources/BlogCategories/Pages/CreateBlogCategory.php b/app/Filament/Admin/Resources/BlogCategories/Pages/CreateBlogCategory.php new file mode 100644 index 0000000..c022cbc --- /dev/null +++ b/app/Filament/Admin/Resources/BlogCategories/Pages/CreateBlogCategory.php @@ -0,0 +1,27 @@ +getResource()::getUrl('index'); + } + + protected function getCreatedNotificationTitle(): ?string + { + return __('blog_category.created_successfully'); + } +} + diff --git a/app/Filament/Admin/Resources/BlogCategories/Pages/EditBlogCategory.php b/app/Filament/Admin/Resources/BlogCategories/Pages/EditBlogCategory.php new file mode 100644 index 0000000..f0d26f5 --- /dev/null +++ b/app/Filament/Admin/Resources/BlogCategories/Pages/EditBlogCategory.php @@ -0,0 +1,62 @@ +label(__('blog_category.save')) + ->action('save') + ->keyBindings(['mod+s']) + ->color('primary') + ->size('sm'), + Action::make('cancel') + ->label(__('blog_category.cancel')) + ->url($this->getResource()::getUrl('index')) + ->color('gray') + ->size('sm'), + DeleteAction::make() + ->label(__('blog_category.delete')) + ->size('sm'), + RestoreAction::make() + ->label(__('blog_category.restore')) + ->size('sm'), + ForceDeleteAction::make() + ->label(__('blog_category.force_delete')) + ->size('sm'), + ]; + } + + protected function getFormActions(): array + { + return []; // Boş array döndürerek alt taraftaki form action'larını gizliyoruz + } + + protected function getRedirectUrl(): string + { + return $this->getResource()::getUrl('index'); + } + + protected function getSavedNotificationTitle(): ?string + { + return __('blog_category.updated_successfully'); + } +} + diff --git a/app/Filament/Admin/Resources/BlogCategories/Pages/ListBlogCategories.php b/app/Filament/Admin/Resources/BlogCategories/Pages/ListBlogCategories.php new file mode 100644 index 0000000..f7ad474 --- /dev/null +++ b/app/Filament/Admin/Resources/BlogCategories/Pages/ListBlogCategories.php @@ -0,0 +1,26 @@ +label(__('blog_category.create')), + ]; + } +} + diff --git a/app/Filament/Admin/Resources/BlogCategories/Schemas/BlogCategoryForm.php b/app/Filament/Admin/Resources/BlogCategories/Schemas/BlogCategoryForm.php new file mode 100644 index 0000000..e114b93 --- /dev/null +++ b/app/Filament/Admin/Resources/BlogCategories/Schemas/BlogCategoryForm.php @@ -0,0 +1,70 @@ +columns(2) + ->schema([ + Section::make(__('blog_category.general_section')) + ->schema([ + TextInput::make('name') + ->label(__('blog_category.name_field')) + ->required() + ->maxLength(255) + ->live(onBlur: true) + ->afterStateUpdated(function (string $operation, $state, callable $set) { + if ($operation !== 'create') { + return; + } + $set('slug', \Str::slug($state)); + }), + + TextInput::make('slug') + ->label(__('blog_category.slug_field')) + ->required() + ->maxLength(255) + ->unique(ignoreRecord: true) + ->rules(['alpha_dash']) + ->helperText(__('blog_category.slug_helper')), + + Textarea::make('description') + ->label(__('blog_category.description_field')) + ->rows(3) + ->maxLength(1000) + ->helperText(__('blog_category.description_helper')) + ->columnSpanFull(), + + ColorPicker::make('color') + ->label(__('blog_category.color_field')) + ->default('#3B82F6') + ->helperText(__('blog_category.color_helper')), + + TextInput::make('sort_order') + ->label(__('blog_category.sort_order_field')) + ->numeric() + ->default(0) + ->helperText(__('blog_category.sort_order_helper')), + + Toggle::make('is_active') + ->label(__('blog_category.is_active_field')) + ->default(true) + ->helperText(__('blog_category.is_active_helper')) + ->columnSpanFull(), + ]) + ->columnSpanFull() + ->collapsible(false), + ]); + } +} + diff --git a/app/Filament/Admin/Resources/BlogCategories/Tables/BlogCategoriesTable.php b/app/Filament/Admin/Resources/BlogCategories/Tables/BlogCategoriesTable.php new file mode 100644 index 0000000..cce4ede --- /dev/null +++ b/app/Filament/Admin/Resources/BlogCategories/Tables/BlogCategoriesTable.php @@ -0,0 +1,93 @@ +columns([ + ColorColumn::make('color') + ->label(__('blog_category.color_field')), + + TextColumn::make('name') + ->label(__('blog_category.name_field')) + ->searchable() + ->sortable() + ->weight('bold'), + + TextColumn::make('slug') + ->label(__('blog_category.slug_field')) + ->searchable() + ->sortable() + ->limit(30) + ->color('gray'), + + TextColumn::make('description') + ->label(__('blog_category.description_field')) + ->limit(50) + ->wrap() + ->toggleable(), + + TextColumn::make('blogs_count') + ->label(__('blog_category.blogs_count')) + ->counts('blogs') + ->sortable() + ->alignCenter(), + + TextColumn::make('sort_order') + ->label(__('blog_category.sort_order_field')) + ->sortable() + ->alignCenter() + ->toggleable(), + + ToggleColumn::make('is_active') + ->label(__('blog_category.is_active_field')) + ->alignCenter(), + + TextColumn::make('created_at') + ->label(__('blog_category.table_created_at')) + ->dateTime('d.m.Y H:i') + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + + TextColumn::make('updated_at') + ->label(__('blog_category.table_updated_at')) + ->dateTime('d.m.Y H:i') + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + ]) + ->filters([ + TernaryFilter::make('is_active') + ->label(__('blog_category.is_active_field')), + ]) + ->recordActions([ + EditAction::make() + ->label(__('blog_category.edit')), + ]) + ->toolbarActions([ + BulkActionGroup::make([ + DeleteBulkAction::make() + ->label(__('blog_category.delete')), + RestoreBulkAction::make() + ->label(__('blog_category.restore')), + ForceDeleteBulkAction::make() + ->label(__('blog_category.force_delete')), + ]), + ]) + ->defaultSort('sort_order'); + } +} + diff --git a/app/Models/BlogCategory.php b/app/Models/BlogCategory.php index 4b4bde3..dbd6725 100644 --- a/app/Models/BlogCategory.php +++ b/app/Models/BlogCategory.php @@ -26,7 +26,7 @@ class BlogCategory extends Model public function blogs() { - return $this->hasMany(Blog::class); + return $this->hasMany(Blog::class, 'category_id'); } public function getRouteKeyName() diff --git a/lang/en/blog_category.php b/lang/en/blog_category.php new file mode 100644 index 0000000..f620f9e --- /dev/null +++ b/lang/en/blog_category.php @@ -0,0 +1,53 @@ + 'Blog Categories', + 'navigation_label' => 'Blog Categories', + 'model_label' => 'Blog Category', + 'plural_model_label' => 'Blog Categories', + + // Actions + 'create' => 'Create New Blog Category', + 'edit' => 'Edit Blog Category', + 'save' => 'Save', + 'cancel' => 'Cancel', + 'delete' => 'Delete Blog Category', + 'restore' => 'Restore Blog Category', + 'force_delete' => 'Force Delete', + + // Sections + 'general_section' => 'General Information', + + // Form fields + 'name_field' => 'Category Name', + 'slug_field' => 'URL Slug', + 'description_field' => 'Description', + 'color_field' => 'Color', + 'sort_order_field' => 'Sort Order', + 'is_active_field' => 'Active', + + // Helper texts + 'slug_helper' => 'The part that will appear in the URL. Example: technology', + 'description_helper' => 'Category description (optional)', + 'color_helper' => 'Select category color (hex format)', + 'sort_order_helper' => 'Category listing order (smaller numbers appear first)', + 'is_active_helper' => 'Activate/deactivate category', + + // Messages + 'created_successfully' => 'Blog category created successfully.', + 'updated_successfully' => 'Blog category updated successfully.', + 'deleted_successfully' => 'Blog category deleted successfully.', + 'restored_successfully' => 'Blog category restored successfully.', + + // Table columns + 'blogs_count' => 'Blog Count', + 'table_created_at' => 'Created At', + 'table_updated_at' => 'Updated At', + + // Validation messages + 'name_required' => 'Category name field is required.', + 'slug_required' => 'URL slug field is required.', + 'slug_unique' => 'This URL slug is already in use.', +]; + diff --git a/lang/tr/blog_category.php b/lang/tr/blog_category.php new file mode 100644 index 0000000..a226a80 --- /dev/null +++ b/lang/tr/blog_category.php @@ -0,0 +1,53 @@ + 'Blog Kategorileri', + 'navigation_label' => 'Blog Kategorileri', + 'model_label' => 'Blog Kategorisi', + 'plural_model_label' => 'Blog Kategorileri', + + // Actions + 'create' => 'Yeni Blog Kategorisi Oluştur', + 'edit' => 'Blog Kategorisini Düzenle', + 'save' => 'Kaydet', + 'cancel' => 'İptal', + 'delete' => 'Blog Kategorisini Sil', + 'restore' => 'Blog Kategorisini Geri Yükle', + 'force_delete' => 'Kalıcı Olarak Sil', + + // Sections + 'general_section' => 'Genel Bilgiler', + + // Form fields + 'name_field' => 'Kategori Adı', + 'slug_field' => 'URL Yolu', + 'description_field' => 'Açıklama', + 'color_field' => 'Renk', + 'sort_order_field' => 'Sıralama', + 'is_active_field' => 'Aktif', + + // Helper texts + 'slug_helper' => 'URL\'de görünecek kısım. Örnek: teknoloji', + 'description_helper' => 'Kategori açıklaması (isteğe bağlı)', + 'color_helper' => 'Kategori rengini seçin (hex formatında)', + 'sort_order_helper' => 'Kategorilerin listelenme sırası (küçük sayılar önce gelir)', + 'is_active_helper' => 'Kategoriyi aktif/pasif yap', + + // Messages + 'created_successfully' => 'Blog kategorisi başarıyla oluşturuldu.', + 'updated_successfully' => 'Blog kategorisi başarıyla güncellendi.', + 'deleted_successfully' => 'Blog kategorisi başarıyla silindi.', + 'restored_successfully' => 'Blog kategorisi başarıyla geri yüklendi.', + + // Table columns + 'blogs_count' => 'Blog Sayısı', + 'table_created_at' => 'Oluşturulma Tarihi', + 'table_updated_at' => 'Güncellenme Tarihi', + + // Validation messages + 'name_required' => 'Kategori adı alanı zorunludur.', + 'slug_required' => 'URL yolu alanı zorunludur.', + 'slug_unique' => 'Bu URL yolu zaten kullanılıyor.', +]; +