diff --git a/docs/MODULE_TEMPLATE.md b/docs/MODULE_TEMPLATE.md new file mode 100644 index 0000000..5f65480 --- /dev/null +++ b/docs/MODULE_TEMPLATE.md @@ -0,0 +1,668 @@ +# Modül Template - Citrus Platform + +## Genel Bakış + +Bu dokümantasyon, Citrus Platform'da yeni modül oluştururken kullanılacak template yapısını ve Pages modülü örneğini detaylandırır. + +## Template Yapısı + +### 1. Dosya Organizasyonu + +``` +app/Filament/Admin/Resources/ModuleName/ +├── ModuleNameResource.php # Ana resource sınıfı +├── Pages/ +│ ├── ListModuleNames.php # Liste sayfası +│ ├── CreateModuleName.php # Oluşturma sayfası +│ └── EditModuleName.php # Düzenleme sayfası +├── Schemas/ +│ └── ModuleNameForm.php # Form şeması +└── Tables/ + └── ModuleNamesTable.php # Tablo şeması + +lang/ +├── tr/ +│ └── module_names.php # Türkçe çeviriler +└── en/ + └── module_names.php # İngilizce çeviriler + +app/Models/ +└── ModuleName.php # Model sınıfı + +database/migrations/ +└── xxxx_create_module_names_table.php # Migration dosyası +``` + +## Template Dosyaları + +### 1. Model Template + +```php + 'datetime', + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + 'deleted_at' => 'datetime', + ]; + + protected $dates = [ + 'published_at', + 'created_at', + 'updated_at', + 'deleted_at', + ]; + + // Scopes + public function scopePublished($query) + { + return $query->where('status', 'published'); + } + + public function scopeDraft($query) + { + return $query->where('status', 'draft'); + } + + // Accessors & Mutators + public function getStatusLabelAttribute() + { + return __('module_names.status_' . $this->status); + } + + public function setSlugAttribute($value) + { + $this->attributes['slug'] = \Str::slug($value); + } +} +``` + +### 2. Migration Template + +```php +id(); + $table->string('title'); + $table->string('slug')->unique(); + $table->longText('content')->nullable(); + $table->enum('status', ['draft', 'published', 'archived'])->default('draft'); + $table->string('meta_title')->nullable(); + $table->text('meta_description')->nullable(); + $table->timestamp('published_at')->nullable(); + $table->timestamps(); + $table->softDeletes(); + + // Indexes + $table->index('status'); + $table->index('published_at'); + $table->index('created_at'); + }); + } + + public function down(): void + { + Schema::dropIfExists('module_names'); + } +}; +``` + +### 3. Resource Template + +```php + ListModuleNames::route('/'), + 'create' => CreateModuleName::route('/create'), + 'edit' => EditModuleName::route('/{record}/edit'), + ]; + } + + // Query + public static function getRecordRouteBindingEloquentQuery(): Builder + { + return parent::getRecordRouteBindingEloquentQuery() + ->withoutGlobalScopes([ + SoftDeletingScope::class, + ]); + } +} +``` + +### 4. List Page Template + +```php +label(__('module_names.create')), + ]; + } +} +``` + +### 5. Create Page Template + +```php +getResource()::getUrl('index'); + } + + protected function getCreatedNotificationTitle(): ?string + { + return __('module_names.created_successfully'); + } +} +``` + +### 6. Edit Page Template + +```php +label(__('module_names.delete')), + ForceDeleteAction::make() + ->label(__('module_names.force_delete')), + RestoreAction::make() + ->label(__('module_names.restore')), + ]; + } + + protected function getRedirectUrl(): string + { + return $this->getResource()::getUrl('index'); + } + + protected function getSavedNotificationTitle(): ?string + { + return __('module_names.updated_successfully'); + } +} +``` + +### 7. Form Schema Template + +```php +schema([ + TextInput::make('title') + ->label(__('module_names.title_field')) + ->required() + ->maxLength(255) + ->validationMessages([ + 'required' => __('module_names.title_required'), + 'max' => __('module_names.title_max'), + ]), + + TextInput::make('slug') + ->label(__('module_names.slug_field')) + ->required() + ->unique(ignoreRecord: true) + ->maxLength(255) + ->validationMessages([ + 'required' => __('module_names.slug_required'), + 'unique' => __('module_names.slug_unique'), + 'max' => __('module_names.slug_max'), + ]), + + Textarea::make('content') + ->label(__('module_names.content_field')) + ->required() + ->rows(10) + ->validationMessages([ + 'required' => __('module_names.content_required'), + ]), + + Select::make('status') + ->label(__('module_names.status_field')) + ->options([ + 'draft' => __('module_names.status_draft'), + 'published' => __('module_names.status_published'), + 'archived' => __('module_names.status_archived'), + ]) + ->default('draft') + ->required(), + + TextInput::make('meta_title') + ->label(__('module_names.meta_title_field')) + ->maxLength(255) + ->validationMessages([ + 'max' => __('module_names.meta_title_max'), + ]), + + Textarea::make('meta_description') + ->label(__('module_names.meta_description_field')) + ->maxLength(500) + ->rows(3) + ->validationMessages([ + 'max' => __('module_names.meta_description_max'), + ]), + + DateTimePicker::make('published_at') + ->label(__('module_names.published_at_field')) + ->nullable(), + ]); + } +} +``` + +### 8. Table Schema Template + +```php +columns([ + TextColumn::make('title') + ->label(__('module_names.table_title')) + ->searchable() + ->sortable() + ->limit(50), + + TextColumn::make('slug') + ->label(__('module_names.table_slug')) + ->searchable() + ->limit(30), + + BadgeColumn::make('status') + ->label(__('module_names.table_status')) + ->colors([ + 'warning' => 'draft', + 'success' => 'published', + 'danger' => 'archived', + ]), + + TextColumn::make('published_at') + ->label(__('module_names.table_published_at')) + ->dateTime() + ->sortable() + ->toggleable(), + + TextColumn::make('created_at') + ->label(__('module_names.table_created_at')) + ->dateTime() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + + TextColumn::make('updated_at') + ->label(__('module_names.table_updated_at')) + ->dateTime() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + ]) + ->filters([ + SelectFilter::make('status') + ->label(__('module_names.status_field')) + ->options([ + 'draft' => __('module_names.status_draft'), + 'published' => __('module_names.status_published'), + 'archived' => __('module_names.status_archived'), + ]), + ]) + ->actions([ + // Table actions + ]) + ->bulkActions([ + BulkActionGroup::make([ + DeleteBulkAction::make(), + ]), + ]) + ->defaultSort('created_at', 'desc'); + } +} +``` + +### 9. Türkçe Dil Dosyası Template + +```php + 'Modül Başlığı', + 'navigation_label' => 'Modül Navigasyon', + 'model_label' => 'Modül', + 'plural_model_label' => 'Modüller', + + // Actions + 'create' => 'Yeni Modül Oluştur', + 'edit' => 'Modülü Düzenle', + 'delete' => 'Modülü Sil', + 'restore' => 'Modülü Geri Yükle', + 'force_delete' => 'Kalıcı Olarak Sil', + + // Form fields + 'title_field' => 'Başlık', + 'slug_field' => 'URL Yolu', + 'content_field' => 'İçerik', + 'status_field' => 'Durum', + 'meta_title_field' => 'Meta Başlık', + 'meta_description_field' => 'Meta Açıklama', + 'published_at_field' => 'Yayın Tarihi', + + // Status options + 'status_draft' => 'Taslak', + 'status_published' => 'Yayınlandı', + 'status_archived' => 'Arşivlendi', + + // Messages + 'created_successfully' => 'Modül başarıyla oluşturuldu.', + 'updated_successfully' => 'Modül başarıyla güncellendi.', + 'deleted_successfully' => 'Modül başarıyla silindi.', + 'restored_successfully' => 'Modül başarıyla geri yüklendi.', + + // Table columns + 'table_title' => 'Başlık', + 'table_slug' => 'URL Yolu', + 'table_status' => 'Durum', + 'table_published_at' => 'Yayın Tarihi', + 'table_created_at' => 'Oluşturulma Tarihi', + 'table_updated_at' => 'Güncellenme Tarihi', + + // Validation messages + 'title_required' => 'Başlık alanı zorunludur.', + 'title_max' => 'Başlık en fazla :max karakter olabilir.', + 'slug_required' => 'URL yolu alanı zorunludur.', + 'slug_unique' => 'Bu URL yolu zaten kullanılıyor.', + 'slug_max' => 'URL yolu en fazla :max karakter olabilir.', + 'content_required' => 'İçerik alanı zorunludur.', + 'meta_title_max' => 'Meta başlık en fazla :max karakter olabilir.', + 'meta_description_max' => 'Meta açıklama en fazla :max karakter olabilir.', +]; +``` + +### 10. İngilizce Dil Dosyası Template + +```php + 'Module Title', + 'navigation_label' => 'Module Navigation', + 'model_label' => 'Module', + 'plural_model_label' => 'Modules', + + // Actions + 'create' => 'Create New Module', + 'edit' => 'Edit Module', + 'delete' => 'Delete Module', + 'restore' => 'Restore Module', + 'force_delete' => 'Force Delete', + + // Form fields + 'title_field' => 'Title', + 'slug_field' => 'URL Slug', + 'content_field' => 'Content', + 'status_field' => 'Status', + 'meta_title_field' => 'Meta Title', + 'meta_description_field' => 'Meta Description', + 'published_at_field' => 'Published At', + + // Status options + 'status_draft' => 'Draft', + 'status_published' => 'Published', + 'status_archived' => 'Archived', + + // Messages + 'created_successfully' => 'Module created successfully.', + 'updated_successfully' => 'Module updated successfully.', + 'deleted_successfully' => 'Module deleted successfully.', + 'restored_successfully' => 'Module restored successfully.', + + // Table columns + 'table_title' => 'Title', + 'table_slug' => 'URL Slug', + 'table_status' => 'Status', + 'table_published_at' => 'Published At', + 'table_created_at' => 'Created At', + 'table_updated_at' => 'Updated At', + + // Validation messages + 'title_required' => 'The title field is required.', + 'title_max' => 'The title may not be greater than :max characters.', + 'slug_required' => 'The URL slug field is required.', + 'slug_unique' => 'This URL slug is already taken.', + 'slug_max' => 'The URL slug may not be greater than :max characters.', + 'content_required' => 'The content field is required.', + 'meta_title_max' => 'The meta title may not be greater than :max characters.', + 'meta_description_max' => 'The meta description may not be greater than :max characters.', +]; +``` + +## Kullanım Rehberi + +### 1. Yeni Modül Oluşturma Adımları + +1. **Model ve Migration Oluştur** +```bash +php artisan make:model ModuleName -m +``` + +2. **Filament Resource Oluştur** +```bash +php artisan make:filament-resource ModuleName --generate +``` + +3. **Dil Dosyalarını Oluştur** +```bash +touch lang/tr/module_names.php +touch lang/en/module_names.php +``` + +4. **Template Dosyalarını Kopyala ve Düzenle** +- Model dosyasını template'e göre düzenle +- Migration dosyasını template'e göre düzenle +- Resource dosyasını template'e göre düzenle +- Page dosyalarını template'e göre düzenle +- Form ve Table dosyalarını template'e göre düzenle +- Dil dosyalarını template'e göre düzenle + +5. **Test Et** +```bash +php artisan test +``` + +### 2. Özelleştirme + +- **Form Alanları**: `ModuleNameForm.php` dosyasında form alanlarını ekle/çıkar +- **Tablo Sütunları**: `ModuleNamesTable.php` dosyasında sütunları ekle/çıkar +- **Validasyon**: Form alanlarında validation kuralları ekle +- **Filtreler**: Tablo filtrelerini ekle +- **İlişkiler**: Model'de ilişkileri tanımla + +### 3. Best Practices + +- ✅ **Naming**: Tutarlı isimlendirme kullan +- ✅ **Localization**: Tüm metinler için çeviri sağla +- ✅ **Validation**: Kapsamlı validation kuralları ekle +- ✅ **Testing**: Test dosyaları yaz +- ✅ **Documentation**: Dokümantasyonu güncel tut +- ❌ **Hardcoded**: Metinleri hardcode etme +- ❌ **Validation**: Validation'ı atlama +- ❌ **Testing**: Test yazmayı unutma + +## Sonuç + +Bu template yapısı, Citrus Platform'da tutarlı ve ölçeklenebilir modül geliştirme sağlar. Pages modülü, bu template'in uygulandığı örnek modüldür ve tüm yeni modüller için referans alınmalıdır. + +### Önemli Noktalar: +1. **Tutarlılık**: Tüm modüller aynı yapıyı kullanmalı +2. **Localization**: Çoklu dil desteği sağlanmalı +3. **Validation**: Kapsamlı form doğrulama yapılmalı +4. **Testing**: Test coverage sağlanmalı +5. **Documentation**: Dokümantasyon güncel tutulmalı