diff --git a/.cursorrules b/.cursorrules
index 871db0a..5d7ba98 100644
--- a/.cursorrules
+++ b/.cursorrules
@@ -210,6 +210,121 @@ $table
**Önemli Not:** Filament 4.x'te `Filament\Resources\Components\Tab` diye bir class **YOK**. Tüm tab kullanımları `Filament\Schemas\Components\Tabs\Tab` ile yapılır!
+#### **Filament 4.x REPEATER KULLANIM KURALLARI (KRİTİK!):**
+
+Repeater component'ı JSON array formatında tekrarlanan form component'leri oluşturmak için kullanılır.
+
+**Temel Kullanım:**
+```php
+use Filament\Forms\Components\Repeater;
+use Filament\Forms\Components\TextInput;
+use Filament\Forms\Components\Select;
+
+Repeater::make('members')
+ ->schema([
+ TextInput::make('name')->required(),
+ Select::make('role')
+ ->options([
+ 'member' => 'Member',
+ 'administrator' => 'Administrator',
+ ])
+ ->required(),
+ ])
+ ->defaultItems(0)
+ ->addActionLabel('Add Member')
+ ->reorderable()
+ ->collapsible()
+ ->itemLabel(fn (array $state): ?string => $state['name'] ?? null)
+```
+
+**Simple Repeater (Tek Field için):**
+```php
+// ✅ DOĞRU - Filament 4.x'te simple() metodu parametre alır
+Repeater::make('tags')
+ ->simple(
+ TextInput::make('tag')
+ ->label('Tag')
+ ->required()
+ )
+
+// ❌ YANLIŞ - Bu kullanım HATA VERİR
+Repeater::make('tags')
+ ->schema([
+ TextInput::make('tag')->required(),
+ ])
+ ->simple() // ❌ Parametre gerekli!
+```
+
+**Nested Repeater ile Dikkat Edilmesi Gerekenler:**
+
+1. **Aynı İsimli Field'lar Çakışır:**
+```php
+// ❌ YANLIŞ - Bu HATA VERİR (FileUpload array beklerken string alır)
+Repeater::make('data')
+ ->schema([
+ TextInput::make('value'), // İlk value
+ FileUpload::make('value'), // İkinci value - ÇAKIŞMA!
+ Textarea::make('value'), // Üçüncü value - ÇAKIŞMA!
+ ])
+
+// ✅ DOĞRU - dehydrated() ile sadece görünür olan kaydedilir
+Repeater::make('data')
+ ->schema([
+ TextInput::make('value')
+ ->visible(fn ($get) => $get('type') === 'text')
+ ->dehydrated(fn ($get) => $get('type') === 'text'),
+
+ FileUpload::make('value')
+ ->visible(fn ($get) => $get('type') === 'image')
+ ->dehydrated(fn ($get) => $get('type') === 'image'),
+
+ Textarea::make('value')
+ ->visible(fn ($get) => $get('type') === 'textarea')
+ ->dehydrated(fn ($get) => $get('type') === 'textarea'),
+ ])
+```
+
+2. **Conditional Field'lar:**
+```php
+// Sadece görünür olan field dehydrate edilir
+Select::make('type')
+ ->options([...])
+ ->live(), // Değişikliği dinlemek için
+
+TextInput::make('value')
+ ->visible(fn (Get $get) => $get('type') === 'text')
+ ->dehydrated(fn (Get $get) => $get('type') === 'text'),
+```
+
+3. **Item Labels:**
+```php
+// Item'lara dinamik label ekle
+Repeater::make('sections')
+ ->schema([...])
+ ->itemLabel(fn (array $state): ?string =>
+ isset($state['type'])
+ ? __('pages.section_type_' . $state['type'])
+ : 'Item'
+ )
+```
+
+4. **Repeater Özellikleri:**
+```php
+Repeater::make('items')
+ ->schema([...])
+ ->defaultItems(0) // Başlangıç item sayısı
+ ->addActionLabel('Add') // Ekleme butonu label'ı
+ ->reorderable() // Sürükle-bırak ile sıralama
+ ->collapsible() // Açılıp kapanabilir
+ ->collapsed() // Başlangıçta kapalı
+ ->cloneable() // Kopyalama butonu
+ ->deletable() // Silme butonu
+ ->minItems(1) // Minimum item sayısı
+ ->maxItems(10) // Maximum item sayısı
+```
+
+**Referans:** [Filament Repeater Docs](https://filamentphp.com/docs/4.x/forms/repeater)
+
### Dil Dosyası Yapısı
collapsible(true)
->collapsed(true),
+ // Sayfa Bölümleri (Section Builder)
+ Section::make(__('pages.form_section_sections'))
+ ->schema([
+ Repeater::make('sections')
+ ->label(__('pages.sections_field'))
+ ->helperText(__('pages.sections_helper_text'))
+ ->schema([
+ Select::make('type')
+ ->label(__('pages.section_type'))
+ ->helperText(__('pages.section_type_helper'))
+ ->required()
+ ->options([
+ 'hero' => __('pages.section_type_hero'),
+ 'features' => __('pages.section_type_features'),
+ 'stats' => __('pages.section_type_stats'),
+ 'cta' => __('pages.section_type_cta'),
+ 'content' => __('pages.section_type_content'),
+ 'gallery' => __('pages.section_type_gallery'),
+ 'testimonials' => __('pages.section_type_testimonials'),
+ 'team' => __('pages.section_type_team'),
+ 'pricing' => __('pages.section_type_pricing'),
+ 'faq' => __('pages.section_type_faq'),
+ 'contact' => __('pages.section_type_contact'),
+ 'custom' => __('pages.section_type_custom'),
+ ])
+ ->live()
+ ->columnSpanFull(),
+
+ Repeater::make('data')
+ ->label(__('pages.section_data'))
+ ->helperText(__('pages.section_data_helper'))
+ ->schema([
+ TextInput::make('key')
+ ->label(__('pages.section_data_key'))
+ ->helperText(__('pages.section_data_key_helper'))
+ ->required()
+ ->placeholder('title, subtitle, image, button_text, ...')
+ ->columnSpan(1),
+
+ Select::make('type')
+ ->label(__('pages.section_data_value_type'))
+ ->required()
+ ->options([
+ 'text' => __('pages.value_type_text'),
+ 'textarea' => __('pages.value_type_textarea'),
+ 'html' => __('pages.value_type_html'),
+ 'markdown' => __('pages.value_type_markdown'),
+ 'richtext' => __('pages.value_type_richtext'),
+ 'image' => __('pages.value_type_image'),
+ 'file' => __('pages.value_type_file'),
+ 'url' => __('pages.value_type_url'),
+ 'email' => __('pages.value_type_email'),
+ 'phone' => __('pages.value_type_phone'),
+ 'number' => __('pages.value_type_number'),
+ 'boolean' => __('pages.value_type_boolean'),
+ 'color' => __('pages.value_type_color'),
+ 'date' => __('pages.value_type_date'),
+ 'datetime' => __('pages.value_type_datetime'),
+ 'array' => __('pages.value_type_array'),
+ 'json' => __('pages.value_type_json'),
+ ])
+ ->live()
+ ->columnSpan(1),
+
+ // Single Hidden Field to store the actual value
+ Hidden::make('value'),
+
+ // Text Input (displays and updates 'value' field)
+ TextInput::make('_value_text')
+ ->label(__('pages.section_data_value'))
+ ->visible(fn (Get $get) => in_array($get('type'), ['text', 'url', 'email', 'phone', 'number']))
+ ->numeric(fn (Get $get) => $get('type') === 'number')
+ ->placeholder('Değer girin...')
+ ->live(onBlur: true)
+ ->afterStateUpdated(fn ($state, callable $set) => $set('value', $state))
+ ->afterStateHydrated(fn ($component, $state, Get $get) => $component->state($get('value')))
+ ->dehydrated(false)
+ ->columnSpanFull(),
+
+ // Textarea (displays and updates 'value' field)
+ Textarea::make('_value_textarea')
+ ->label(__('pages.section_data_value'))
+ ->visible(fn (Get $get) => in_array($get('type'), ['textarea', 'json', 'html']))
+ ->rows(fn (Get $get) => $get('type') === 'html' ? 6 : 4)
+ ->placeholder(fn (Get $get) => $get('type') === 'html' ? '
HTML kodu girin...
' : 'Metin girin...')
+ ->live(onBlur: true)
+ ->afterStateUpdated(fn ($state, callable $set) => $set('value', $state))
+ ->afterStateHydrated(fn ($component, $state, Get $get) => $component->state($get('value')))
+ ->dehydrated(false)
+ ->columnSpanFull(),
+
+ // Rich Text Editor (displays and updates 'value' field)
+ RichEditor::make('_value_richtext')
+ ->label(__('pages.section_data_value'))
+ ->visible(fn (Get $get) => $get('type') === 'richtext')
+ ->fileAttachmentsDisk('public')
+ ->fileAttachmentsDirectory('pages/sections')
+ ->toolbarButtons([
+ 'bold',
+ 'italic',
+ 'link',
+ 'bulletList',
+ 'orderedList',
+ ])
+ ->live(onBlur: true)
+ ->afterStateUpdated(fn ($state, callable $set) => $set('value', $state))
+ ->afterStateHydrated(fn ($component, $state, Get $get) => $component->state($get('value')))
+ ->dehydrated(false)
+ ->columnSpanFull(),
+
+ // Markdown Editor (displays and updates 'value' field)
+ MarkdownEditor::make('_value_markdown')
+ ->label(__('pages.section_data_value'))
+ ->visible(fn (Get $get) => $get('type') === 'markdown')
+ ->live(onBlur: true)
+ ->afterStateUpdated(fn ($state, callable $set) => $set('value', $state))
+ ->afterStateHydrated(fn ($component, $state, Get $get) => $component->state($get('value')))
+ ->dehydrated(false)
+ ->columnSpanFull(),
+
+ // Image Upload (displays and updates 'value' field)
+ FileUpload::make('_value_image')
+ ->label(__('pages.section_data_value'))
+ ->visible(fn (Get $get) => $get('type') === 'image')
+ ->image()
+ ->disk('public')
+ ->directory('pages/sections')
+ ->imageEditor()
+ ->live()
+ ->afterStateUpdated(fn ($state, callable $set) => $set('value', $state))
+ ->afterStateHydrated(fn ($component, $state, Get $get) => $component->state($get('value')))
+ ->dehydrated(false)
+ ->columnSpanFull(),
+
+ // File Upload (displays and updates 'value' field)
+ FileUpload::make('_value_file')
+ ->label(__('pages.section_data_value'))
+ ->visible(fn (Get $get) => $get('type') === 'file')
+ ->disk('public')
+ ->directory('pages/sections')
+ ->live()
+ ->afterStateUpdated(fn ($state, callable $set) => $set('value', $state))
+ ->afterStateHydrated(fn ($component, $state, Get $get) => $component->state($get('value')))
+ ->dehydrated(false)
+ ->columnSpanFull(),
+
+ // Boolean Toggle (displays and updates 'value' field)
+ Toggle::make('_value_boolean')
+ ->label(__('pages.section_data_value'))
+ ->visible(fn (Get $get) => $get('type') === 'boolean')
+ ->live()
+ ->afterStateUpdated(fn ($state, callable $set) => $set('value', $state))
+ ->afterStateHydrated(fn ($component, $state, Get $get) => $component->state($get('value')))
+ ->dehydrated(false)
+ ->columnSpanFull(),
+
+ // Color Picker (displays and updates 'value' field)
+ ColorPicker::make('_value_color')
+ ->label(__('pages.section_data_value'))
+ ->visible(fn (Get $get) => $get('type') === 'color')
+ ->live(onBlur: true)
+ ->afterStateUpdated(fn ($state, callable $set) => $set('value', $state))
+ ->afterStateHydrated(fn ($component, $state, Get $get) => $component->state($get('value')))
+ ->dehydrated(false)
+ ->columnSpanFull(),
+
+ // Date Picker (displays and updates 'value' field)
+ DatePicker::make('_value_date')
+ ->label(__('pages.section_data_value'))
+ ->visible(fn (Get $get) => $get('type') === 'date')
+ ->displayFormat('d/m/Y')
+ ->live()
+ ->afterStateUpdated(fn ($state, callable $set) => $set('value', $state))
+ ->afterStateHydrated(fn ($component, $state, Get $get) => $component->state($get('value')))
+ ->dehydrated(false)
+ ->columnSpanFull(),
+
+ // DateTime Picker (displays and updates 'value' field)
+ DateTimePicker::make('_value_datetime')
+ ->label(__('pages.section_data_value'))
+ ->visible(fn (Get $get) => $get('type') === 'datetime')
+ ->displayFormat('d/m/Y H:i')
+ ->seconds(false)
+ ->live()
+ ->afterStateUpdated(fn ($state, callable $set) => $set('value', $state))
+ ->afterStateHydrated(fn ($component, $state, Get $get) => $component->state($get('value')))
+ ->dehydrated(false)
+ ->columnSpanFull(),
+
+ // Array Repeater (displays and updates 'value' field)
+ Repeater::make('_value_array')
+ ->label(__('pages.section_data_value'))
+ ->visible(fn (Get $get) => $get('type') === 'array')
+ ->simple(
+ TextInput::make('item')
+ ->label('Öğe')
+ ->required()
+ )
+ ->live(onBlur: true)
+ ->afterStateUpdated(fn ($state, callable $set) => $set('value', $state))
+ ->afterStateHydrated(fn ($component, $state, Get $get) => $component->state($get('value')))
+ ->dehydrated(false)
+ ->columnSpanFull(),
+ ])
+ ->columns(2)
+ ->defaultItems(0)
+ ->addActionLabel(__('pages.section_data_add_field'))
+ ->reorderable()
+ ->collapsible()
+ ->itemLabel(fn (array $state): ?string => isset($state['key']) ? $state['key'] . ' (' . ($state['type'] ?? 'text') . ')' : null)
+ ->columnSpanFull(),
+ ])
+ ->defaultItems(0)
+ ->addActionLabel(__('pages.section_add'))
+ ->reorderable()
+ ->collapsible()
+ ->itemLabel(fn (array $state): ?string => isset($state['type']) ? __('pages.section_type_' . $state['type']) : 'Bölüm')
+ ->columnSpanFull(),
+ ])
+ ->columnSpanFull()
+ ->collapsible(true)
+ ->collapsed(false),
+
// Çeviri Sekmesi
Section::make('🌍 ' . __('pages.translations_section'))
->schema([
diff --git a/app/Http/Controllers/PageController.php b/app/Http/Controllers/PageController.php
index d3095cb..a23b609 100644
--- a/app/Http/Controllers/PageController.php
+++ b/app/Http/Controllers/PageController.php
@@ -92,7 +92,8 @@ class PageController extends Controller
? ($page->translate('meta_description') ?: ($page->excerpt ?? null))
: ($page->meta_description ?? $page->excerpt ?? null);
- $sections = $page->sections ?? $page->data ?? [];
+ // Use parsed_sections for easier template usage (key-value format)
+ $sections = $page->parsed_sections ?? $page->sections ?? $page->data ?? [];
$template = ($slug === 'home' || ($page->is_homepage ?? false))
? 'home'
: ($page->template ?? 'generic');
diff --git a/app/Models/Page.php b/app/Models/Page.php
index e560ac8..38da609 100644
--- a/app/Models/Page.php
+++ b/app/Models/Page.php
@@ -88,4 +88,40 @@ class Page extends Model
return null;
}
+
+ /**
+ * Get sections with parsed data as associative array
+ */
+ public function getParsedSectionsAttribute()
+ {
+ if (!$this->sections || !is_array($this->sections)) {
+ return [];
+ }
+
+ return collect($this->sections)->map(function ($section) {
+ if (!isset($section['data']) || !is_array($section['data'])) {
+ return $section;
+ }
+
+ // Convert key-value-type array to associative array
+ $parsedData = collect($section['data'])->pluck('value', 'key')->toArray();
+
+ return [
+ 'type' => $section['type'] ?? null,
+ 'data' => $parsedData,
+ ];
+ })->toArray();
+ }
+
+ /**
+ * Get a specific section's data by type
+ */
+ public function getSectionData(string $type, int $index = 0): ?array
+ {
+ $sections = $this->parsed_sections;
+ $matchingSections = array_filter($sections, fn($s) => ($s['type'] ?? null) === $type);
+ $matchingSections = array_values($matchingSections);
+
+ return $matchingSections[$index] ?? null;
+ }
}
diff --git a/docs/SECTION_BUILDER.md b/docs/SECTION_BUILDER.md
new file mode 100644
index 0000000..60bbc76
--- /dev/null
+++ b/docs/SECTION_BUILDER.md
@@ -0,0 +1,389 @@
+# Page Section Builder - Kullanım Kılavuzu
+
+## 📋 Genel Bakış
+
+Page Section Builder, Filament Admin panelinden sayfalarınıza dinamik bölümler (sections) eklemenizi sağlayan güçlü bir modüldür. Settings modülünden esinlenerek geliştirilmiş olup, esnek bir key-value-type sistemi kullanır.
+
+## ✨ Özellikler
+
+- **Dinamik Section Tipleri**: Hero, Features, Stats, CTA, Gallery, Testimonials ve daha fazlası
+- **Esnek Data Yönetimi**: Her section için sınırsız key-value çifti
+- **Çoklu Value Tipleri**: Text, Image, HTML, Rich Text, Markdown, Color, Date, Array ve daha fazlası
+- **Sürükle-Bırak Sıralama**: Sections ve data fields'ları yeniden sıralayabilme
+- **Kolay Entegrasyon**: Mevcut sayfalarda sorunsuz çalışır
+
+## 🎯 Section Tipleri
+
+Aşağıdaki section tipleri mevcuttur:
+
+| Tip | Açıklama | Kullanım Alanı |
+|-----|----------|----------------|
+| `hero` | Hero (Ana Banner) | Sayfa başlığı, büyük görsel banner |
+| `features` | Özellikler | Ürün/hizmet özellikleri listesi |
+| `stats` | İstatistikler | Sayısal veriler, başarı metrikleri |
+| `cta` | Harekete Geçirme | Kullanıcıyı yönlendirme butonları |
+| `content` | İçerik | Genel içerik blokları |
+| `gallery` | Galeri | Görsel galeri |
+| `testimonials` | Referanslar | Müşteri yorumları |
+| `team` | Ekip | Ekip üyeleri |
+| `pricing` | Fiyatlandırma | Fiyat tabloları |
+| `faq` | SSS | Sık sorulan sorular |
+| `contact` | İletişim | İletişim formu |
+| `custom` | Özel | Özel içerik |
+
+## 📝 Value Tipleri
+
+Her data field'ı için aşağıdaki value tipleri kullanılabilir:
+
+### Metin Tipleri
+- **Text**: Kısa tek satırlık metin (başlık, URL, e-posta, telefon)
+- **Textarea**: Uzun metin
+- **HTML**: Ham HTML kodu
+- **Markdown**: Markdown formatı
+- **Rich Text**: WYSIWYG zengin metin editörü
+
+### Medya Tipleri
+- **Image**: Görsel yükleme (otomatik image editor ile)
+- **File**: Dosya yükleme
+- **Color**: Renk seçici
+
+### Veri Tipleri
+- **Number**: Sayısal değer
+- **Boolean**: Evet/Hayır (Toggle)
+- **Date**: Tarih seçici
+- **DateTime**: Tarih & saat seçici
+- **Array**: Dizi (repeater)
+- **JSON**: JSON formatı
+
+## 🔧 Admin Panelinde Kullanım
+
+### 1. Yeni Section Ekleme
+
+1. **Pages** modülünden bir sayfa açın veya yeni sayfa oluşturun
+2. **Sayfa Bölümleri** (Page Sections) sekmesine gidin
+3. **Yeni Bölüm Ekle** butonuna tıklayın
+4. Section tipini seçin (örn: Hero, Features)
+5. **Yeni Alan Ekle** ile section data'larını ekleyin
+
+### 2. Data Field Ekleme
+
+Her section için data field'ları eklerken:
+
+1. **Key (Anahtar)**: Data'nın anahtarı (örn: `title`, `subtitle`, `image`)
+2. **Type (Değer Tipi)**: Değerin tipini seçin (örn: Text, Image, HTML)
+3. **Value (Değer)**: Seçilen tipe göre değeri girin
+
+### 3. Örnek: Hero Section Oluşturma
+
+```
+Section Type: Hero (Ana Banner)
+
+Data Fields:
+┌─────────────────────────────────────────┐
+│ Key: background_image │
+│ Type: Image │
+│ Value: [Upload Image] │
+├─────────────────────────────────────────┤
+│ Key: badge │
+│ Type: Text │
+│ Value: "YENİ PLATFORM" │
+├─────────────────────────────────────────┤
+│ Key: title │
+│ Type: HTML │
+│ Value: "Modern Web" │
+├─────────────────────────────────────────┤
+│ Key: subtitle │
+│ Type: Textarea │
+│ Value: "Açıklama metni..." │
+├─────────────────────────────────────────┤
+│ Key: button_text │
+│ Type: Text │
+│ Value: "Hemen Başla" │
+├─────────────────────────────────────────┤
+│ Key: button_url │
+│ Type: URL │
+│ Value: "#features" │
+└─────────────────────────────────────────┘
+```
+
+## 💻 Kod Kullanımı
+
+### Page Model'de Sections Kullanımı
+
+```php
+// Bir sayfayı al
+$page = Page::find(1);
+
+// Tüm parsed sections'ları al (key-value formatında)
+$sections = $page->parsed_sections;
+
+// Örnek çıktı:
+[
+ [
+ 'type' => 'hero',
+ 'data' => [
+ 'background_image' => 'path/to/image.jpg',
+ 'badge' => 'YENİ PLATFORM',
+ 'title' => 'Modern Web',
+ 'subtitle' => 'Açıklama metni...',
+ 'button_text' => 'Hemen Başla',
+ 'button_url' => '#features',
+ ]
+ ],
+ [
+ 'type' => 'features',
+ 'data' => [...]
+ ]
+]
+
+// Belirli bir section tipinin data'sını al
+$heroData = $page->getSectionData('hero'); // İlk hero section
+$secondHero = $page->getSectionData('hero', 1); // İkinci hero section
+```
+
+### Controller'da Kullanım
+
+```php
+public function show($slug)
+{
+ $page = Page::where('slug', $slug)->firstOrFail();
+
+ // Parsed sections otomatik olarak view'e gönderilir
+ $sections = $page->parsed_sections;
+
+ return view('templates.home', compact('page', 'sections'));
+}
+```
+
+### Blade Template'de Kullanım
+
+```blade
+@foreach($sections as $section)
+ @if($section['type'] === 'hero')
+
+
+ @elseif($section['type'] === 'features')
+
+
+ @elseif($section['type'] === 'stats')
+
+
+ @endif
+@endforeach
+```
+
+### Component'te Data Kullanımı
+
+```blade
+{{-- resources/views/components/blocks/hero.blade.php --}}
+
+@props(['data'])
+
+
+
+ @if(isset($data['badge']))
+
{{ $data['badge'] }}
+ @endif
+
+ @if(isset($data['title']))
+
{!! $data['title'] !!}
+ @endif
+
+ @if(isset($data['subtitle']))
+
{{ $data['subtitle'] }}
+ @endif
+
+ @if(isset($data['button_text']) && isset($data['button_url']))
+
+ {{ $data['button_text'] }}
+
+ @endif
+
+
+```
+
+## 🎨 Best Practices
+
+### 1. Key Naming (Anahtar İsimlendirme)
+
+Tutarlı ve açıklayıcı key isimleri kullanın:
+
+```
+✅ İYİ:
+- title
+- subtitle
+- background_image
+- primary_button_text
+- primary_button_url
+
+❌ KÖTÜ:
+- baslik
+- resim1
+- text
+- btn
+```
+
+### 2. Value Type Seçimi
+
+Doğru value tipini seçin:
+
+```
+✅ title → Text (kısa başlık)
+✅ description → Textarea (uzun açıklama)
+✅ content → Rich Text (formatlanmış içerik)
+✅ banner → Image (görsel)
+✅ is_active → Boolean (aktif/pasif)
+```
+
+### 3. Section Organization
+
+Benzer section'ları gruplandırın:
+
+```
+1. Hero (Giriş)
+2. Features (Özellikler)
+3. Stats (İstatistikler)
+4. CTA (Harekete Geçirme)
+5. Contact (İletişim)
+```
+
+## 🔄 Mevcut Data Migrasyon
+
+Eğer eski formatınız varsa (örn: PageSeeder'daki gibi), parse edilmiş format otomatik olarak çalışır:
+
+```php
+// ESKİ FORMAT (PageSeeder'dan)
+'sections' => [
+ [
+ 'type' => 'hero',
+ 'data' => [
+ 'title' => 'Başlık',
+ 'subtitle' => 'Alt başlık'
+ ]
+ ]
+]
+
+// YENİ FORMAT (Admin'den girilince)
+'sections' => [
+ [
+ 'type' => 'hero',
+ 'data' => [
+ ['key' => 'title', 'type' => 'text', 'value' => 'Başlık'],
+ ['key' => 'subtitle', 'type' => 'text', 'value' => 'Alt başlık']
+ ]
+ ]
+]
+
+// parsed_sections attribute her ikisini de doğru parse eder!
+```
+
+## 🚀 İleri Seviye Özellikler
+
+### Nested Arrays (İç İçe Diziler)
+
+`Array` value tipi ile iç içe veri yapıları oluşturabilirsiniz:
+
+```
+Section Type: Features
+
+Data Field:
+Key: features
+Type: Array
+Value: [
+ { item: "Hızlı Çözümler" },
+ { item: "Güvenli Altyapı" },
+ { item: "Uzman Ekip" }
+]
+```
+
+### JSON Data
+
+Kompleks veri yapıları için JSON kullanabilirsiniz:
+
+```
+Key: configuration
+Type: JSON
+Value: {"layout": "grid", "columns": 3, "gap": 20}
+```
+
+### Conditional Rendering
+
+```blade
+@foreach($sections as $section)
+ @php
+ $data = $section['data'];
+ $bgClass = $data['bg_class'] ?? '';
+ @endphp
+
+
+ @includeIf("components.blocks.{$section['type']}", compact('data'))
+
+@endforeach
+```
+
+## 📚 Dosya Yapısı
+
+```
+app/
+├── Models/
+│ └── Page.php (getParsedSectionsAttribute, getSectionData)
+├── Http/Controllers/
+│ └── PageController.php (parsed_sections kullanımı)
+└── Filament/Admin/Resources/Pages/
+ └── Schemas/
+ └── PageForm.php (Section Builder UI)
+
+lang/
+├── tr/
+│ └── pages.php (Türkçe çeviriler)
+└── en/
+ └── pages.php (İngilizce çeviriler)
+
+resources/views/
+├── components/blocks/
+│ ├── hero.blade.php
+│ ├── features.blade.php
+│ ├── stats.blade.php
+│ └── cta.blade.php
+└── templates/
+ └── home.blade.php (sections render)
+```
+
+## 🐛 Troubleshooting
+
+### Section görünmüyor?
+
+1. `$page->parsed_sections` döndüğünden emin olun
+2. Section type'ının doğru yazıldığını kontrol edin
+3. Blade component'in var olduğunu doğrulayın
+
+### Data değerleri boş?
+
+1. Admin'de data field'larının key değerlerini kontrol edin
+2. Value tipinin doğru seçildiğini doğrulayın
+3. Değerlerin kaydedildiğini kontrol edin
+
+### Image görünmüyor?
+
+1. `storage` link'inin oluşturulduğunu kontrol edin: `php artisan storage:link`
+2. Image path'inin doğru olduğunu doğrulayın
+3. Disk ayarlarını kontrol edin (`config/filesystems.php`)
+
+## 🎓 Örnekler
+
+Daha fazla örnek için:
+- `database/seeders/PageSeeder.php` - Mevcut section örnekleri
+- `resources/views/components/blocks/` - Component örnekleri
+- `resources/views/templates/home.blade.php` - Template örneği
+
+## 📞 Destek
+
+Sorunlarınız için:
+1. Bu dokümantasyonu kontrol edin
+2. `docs/CURSOR_RULES.md` dosyasına bakın
+3. Loglara göz atın: `storage/logs/laravel.log`
+
+---
+
+**Not:** Bu sistem Settings modülünden esinlenerek geliştirilmiş olup, aynı esneklik ve güçle çalışır. Her türlü dinamik sayfa içeriği için kullanılabilir.
+
diff --git a/lang/en/pages.php b/lang/en/pages.php
index 4b64983..460cef7 100644
--- a/lang/en/pages.php
+++ b/lang/en/pages.php
@@ -24,6 +24,7 @@ return [
'form_section_content' => 'Content',
'form_section_page_settings' => 'Page Settings',
'form_section_seo_settings' => 'SEO Settings',
+ 'form_section_sections' => 'Page Sections',
'translations_section' => 'Translations',
// Form fields
@@ -95,4 +96,53 @@ return [
'slug_required' => 'The URL slug field is required.',
'slug_unique' => 'This URL slug is already taken.',
'content_required' => 'The content field is required.',
+
+ // Section Builder
+ 'sections_field' => 'Page Sections',
+ 'sections_helper_text' => 'Add dynamic sections to your page',
+ 'section_type' => 'Section Type',
+ 'section_type_helper' => 'Select the type of section you want to add',
+ 'section_data' => 'Section Data',
+ 'section_data_helper' => 'Enter the required data for this section',
+ 'section_add' => 'Add New Section',
+
+ // Section Types
+ 'section_type_hero' => 'Hero (Main Banner)',
+ 'section_type_features' => 'Features',
+ 'section_type_stats' => 'Statistics',
+ 'section_type_cta' => 'Call to Action',
+ 'section_type_content' => 'Content',
+ 'section_type_gallery' => 'Gallery',
+ 'section_type_testimonials' => 'Testimonials',
+ 'section_type_team' => 'Team',
+ 'section_type_pricing' => 'Pricing',
+ 'section_type_faq' => 'FAQ',
+ 'section_type_contact' => 'Contact',
+ 'section_type_custom' => 'Custom',
+
+ // Section Data Fields
+ 'section_data_key' => 'Key',
+ 'section_data_key_helper' => 'Data key (e.g: title, subtitle, image)',
+ 'section_data_value_type' => 'Value Type',
+ 'section_data_value' => 'Value',
+ 'section_data_add_field' => 'Add New Field',
+
+ // Value Types
+ 'value_type_text' => 'Text',
+ 'value_type_textarea' => 'Long Text',
+ 'value_type_html' => 'HTML',
+ 'value_type_markdown' => 'Markdown',
+ 'value_type_richtext' => 'Rich Text',
+ 'value_type_image' => 'Image',
+ 'value_type_file' => 'File',
+ 'value_type_url' => 'URL',
+ 'value_type_email' => 'Email',
+ 'value_type_phone' => 'Phone',
+ 'value_type_number' => 'Number',
+ 'value_type_boolean' => 'Yes/No',
+ 'value_type_color' => 'Color',
+ 'value_type_date' => 'Date',
+ 'value_type_datetime' => 'Date & Time',
+ 'value_type_array' => 'Array',
+ 'value_type_json' => 'JSON',
];
diff --git a/lang/tr/pages.php b/lang/tr/pages.php
index aaba588..cf61433 100644
--- a/lang/tr/pages.php
+++ b/lang/tr/pages.php
@@ -24,6 +24,7 @@ return [
'form_section_content' => 'İçerik',
'form_section_page_settings' => 'Sayfa Ayarları',
'form_section_seo_settings' => 'SEO Ayarları',
+ 'form_section_sections' => 'Sayfa Bölümleri',
'translations_section' => 'Çeviriler',
// Form fields
@@ -95,4 +96,53 @@ return [
'slug_required' => 'URL yolu alanı zorunludur.',
'slug_unique' => 'Bu URL yolu zaten kullanılıyor.',
'content_required' => 'İçerik alanı zorunludur.',
+
+ // Section Builder
+ 'sections_field' => 'Sayfa Bölümleri',
+ 'sections_helper_text' => 'Sayfanız için dinamik bölümler ekleyin',
+ 'section_type' => 'Bölüm Tipi',
+ 'section_type_helper' => 'Eklemek istediğiniz bölüm tipini seçin',
+ 'section_data' => 'Bölüm Verileri',
+ 'section_data_helper' => 'Bu bölüm için gerekli verileri girin',
+ 'section_add' => 'Yeni Bölüm Ekle',
+
+ // Section Types
+ 'section_type_hero' => 'Hero (Ana Banner)',
+ 'section_type_features' => 'Özellikler',
+ 'section_type_stats' => 'İstatistikler',
+ 'section_type_cta' => 'Harekete Geçirme',
+ 'section_type_content' => 'İçerik',
+ 'section_type_gallery' => 'Galeri',
+ 'section_type_testimonials' => 'Referanslar',
+ 'section_type_team' => 'Ekip',
+ 'section_type_pricing' => 'Fiyatlandırma',
+ 'section_type_faq' => 'SSS',
+ 'section_type_contact' => 'İletişim',
+ 'section_type_custom' => 'Özel',
+
+ // Section Data Fields
+ 'section_data_key' => 'Anahtar',
+ 'section_data_key_helper' => 'Veri anahtarı (örn: title, subtitle, image)',
+ 'section_data_value_type' => 'Değer Tipi',
+ 'section_data_value' => 'Değer',
+ 'section_data_add_field' => 'Yeni Alan Ekle',
+
+ // Value Types
+ 'value_type_text' => 'Metin',
+ 'value_type_textarea' => 'Uzun Metin',
+ 'value_type_html' => 'HTML',
+ 'value_type_markdown' => 'Markdown',
+ 'value_type_richtext' => 'Zengin Metin',
+ 'value_type_image' => 'Görsel',
+ 'value_type_file' => 'Dosya',
+ 'value_type_url' => 'URL',
+ 'value_type_email' => 'E-posta',
+ 'value_type_phone' => 'Telefon',
+ 'value_type_number' => 'Sayı',
+ 'value_type_boolean' => 'Evet/Hayır',
+ 'value_type_color' => 'Renk',
+ 'value_type_date' => 'Tarih',
+ 'value_type_datetime' => 'Tarih & Saat',
+ 'value_type_array' => 'Dizi',
+ 'value_type_json' => 'JSON',
];