# Admin Panel — Site Ayarları Modülü

## Genel Bakış

Backend'de `settings` tablosu güncellendi. Artık her ayarın **label** (Türkçe etiket) ve **order_index** (sıralama) alanları var. Ayarlar **9 gruba** ayrılmış durumda. Admin panelde her grup kendi sekmesi/sayfası olacak.

---

## API Endpoints

Tüm admin endpoint'leri `auth:sanctum` ile korunuyor. Base URL: `{API_URL}/api/admin`

| Method | Endpoint | Açıklama |
|--------|----------|----------|
| `GET` | `/admin/settings` | Tüm ayarları flat liste olarak getir |
| `GET` | `/admin/settings/group/{group}` | Tek grup ayarlarını getir |
| `PUT` | `/admin/settings` | Toplu güncelleme (dot notation) |
| `POST` | `/admin/settings/clear-cache` | Ayar cache'ini temizle |

---

## GET /admin/settings — Tüm Ayarlar

Her ayar şu formatta döner:

```json
{
  "data": [
    {
      "id": 1,
      "key": "site_name",
      "value": "Boğaziçi Denizcilik Eğitim Kurumu",
      "group": "general",
      "type": "text",
      "label": "Site Adı",
      "order_index": 0
    },
    {
      "id": 8,
      "key": "announcement_bar_active",
      "value": "true",
      "group": "general",
      "type": "boolean",
      "label": "Üst Bar Aktif mi",
      "order_index": 7
    }
  ]
}
```

**Frontend'de `group` bazında filtrele** → Her sekme/tab kendi grubunu gösterir.

---

## GET /admin/settings/group/{group} — Tek Grup

Sadece o grubun ayarlarını döner. `order_index` sıralı gelir.

Geçerli group değerleri:
- `general` — Genel site ayarları
- `contact` — İletişim bilgileri
- `maps` — Harita ayarları
- `social` — Sosyal medya linkleri
- `seo` — SEO, Open Graph, Twitter Card, doğrulama kodları
- `analytics` — Google Analytics, Tag Manager, Pixel ID'leri
- `header` — Navbar ve üst bar ayarları
- `footer` — Footer içerik ve stili
- `integrations` — SMTP, reCAPTCHA, bildirim ayarları

---

## PUT /admin/settings — Toplu Güncelleme

**Dot notation** formatında gönder: `{group}.{key}: value`

### Request Body:

```json
{
  "settings": {
    "general.site_name": "Yeni Site Adı",
    "general.announcement_bar_active": "true",
    "contact.phone_primary": "+90 555 123 45 67",
    "social.instagram_url": "https://instagram.com/bogazicidenizcilik",
    "header.cta_button_text": "Kayıt Ol",
    "footer.copyright_text": "© 2026 Boğaziçi Denizcilik"
  }
}
```

### Response:
```json
{ "message": "Ayarlar güncellendi." }
```

### Önemli:
- Sadece değişen ayarları gönderin, hepsini göndermenize gerek yok
- PUT sonrası backend otomatik olarak tüm cache'leri temizler
- Validation: `settings` required array, her value nullable string

---

## POST /admin/settings/clear-cache

Body gerekmez. Manuel cache temizleme butonu için.

```json
{ "message": "Ayar cache temizlendi." }
```

---

## Type'lara Göre Form Bileşenleri

Her ayarın `type` alanı, admin panelde hangi input bileşeninin kullanılacağını belirler:

| type | Bileşen | Açıklama |
|------|---------|----------|
| `text` | `<input type="text">` | Tek satır metin |
| `textarea` | `<textarea>` | Çok satır metin |
| `image` | Dosya yükleme + önizleme | Mevcut upload endpoint'i kullanılır (`POST /admin/uploads`) |
| `boolean` | Toggle/Switch | value `"true"` veya `"false"` string olarak saklanır |
| `url` | `<input type="url">` | URL formatı |
| `color` | Color picker | Hex renk kodu (#RRGGBB) |
| `richtext` | TipTap / zengin metin editör | HTML içerik |
| `json` | JSON editör | Yapısal veri |

### Boolean Değerler
Backend'de `value` her zaman **string** olarak saklanır. Boolean'lar `"true"` / `"false"` string:
```js
// Gönderirken
{ "settings": { "general.maintenance_mode": "false" } }

// Okurken
setting.value === "true" // → toggle ON
setting.value === "false" // → toggle OFF
```

### Image Alanları
1. Dosyayı `POST /admin/uploads` ile yükle → response'dan URL al
2. URL'yi settings update'e gönder:
```json
{ "settings": { "general.logo_light": "/storage/uploads/logo-white.png" } }
```

---

## Grup Detayları ve Alanlar

### general (13 alan)
| key | type | label |
|-----|------|-------|
| site_name | text | Site Adı |
| site_tagline | text | Slogan |
| site_description | textarea | Kısa Site Açıklaması |
| logo_light | image | Logo — Açık Tema (beyaz navbar) |
| logo_dark | image | Logo — Koyu Tema (dark bg) |
| favicon | image | Favicon (32x32 PNG) |
| apple_touch_icon | image | Apple Touch Icon (180x180) |
| announcement_bar_active | boolean | Üst Bar Aktif mi |
| announcement_bar_text | text | Üst Bar Metni |
| announcement_bar_url | url | Üst Bar Linki |
| announcement_bar_bg_color | color | Üst Bar Arka Plan Rengi |
| maintenance_mode | boolean | Bakım Modu |
| maintenance_message | textarea | Bakım Modu Mesajı |

### contact (15 alan)
| key | type | label |
|-----|------|-------|
| phone_primary | text | Ana Telefon |
| phone_secondary | text | İkinci Telefon |
| email_info | text | Bilgi E-postası |
| email_support | text | Destek E-postası |
| email_kayit | text | Kayıt E-postası |
| address_full | textarea | Tam Adres |
| address_short | text | Kısa Adres (navbar için) |
| district | text | İlçe |
| city | text | Şehir |
| postal_code | text | Posta Kodu |
| working_hours_weekday | text | Hafta İçi Saatleri |
| working_hours_saturday | text | Cumartesi Saatleri |
| working_hours_sunday | text | Pazar Saatleri |
| whatsapp_number | text | WhatsApp (+90 ile başlayan) |
| whatsapp_message | text | WhatsApp Varsayılan Mesaj |

### maps (6 alan)
| key | type | label |
|-----|------|-------|
| google_maps_embed_url | textarea | Google Maps Embed URL (iframe src) |
| google_maps_place_url | url | Google Maps Profil Linki |
| google_maps_api_key | text | Google Maps API Key |
| latitude | text | Enlem |
| longitude | text | Boylam |
| map_zoom_level | text | Harita Zoom (1-20) |

> **Not:** `google_maps_api_key` admin endpoint'ten görünür ama public API'den filtrelenir.

### social (11 alan)
| key | type | label |
|-----|------|-------|
| instagram_url | url | Instagram Profil URL |
| instagram_handle | text | Instagram Kullanıcı Adı (@siz) |
| facebook_url | url | Facebook Sayfası URL |
| facebook_page_id | text | Facebook Page ID |
| twitter_url | url | X (Twitter) Profil URL |
| twitter_handle | text | X Kullanıcı Adı (@siz) |
| youtube_url | url | YouTube Kanal URL |
| youtube_channel_id | text | YouTube Channel ID |
| linkedin_url | url | LinkedIn Sayfa URL |
| tiktok_url | url | TikTok Profil URL |
| pinterest_url | url | Pinterest URL |

### seo (23 alan)

**Temel SEO:**
| key | type | label |
|-----|------|-------|
| meta_title_suffix | text | Title Eki |
| meta_title_separator | text | Ayraç Karakteri |
| default_meta_description | textarea | Varsayılan Meta Açıklama |
| default_meta_keywords | textarea | Varsayılan Keywords (virgülle) |
| robots | text | Robots |
| canonical_domain | url | Canonical Domain |

**Open Graph:**
| key | type | label |
|-----|------|-------|
| og_title | text | OG Default Title |
| og_description | textarea | OG Default Description |
| og_image | image | OG Default Görsel (1200x630 px) |
| og_type | text | OG Type |
| og_locale | text | OG Locale |
| og_site_name | text | OG Site Name |
| facebook_app_id | text | Facebook App ID |

**Twitter / X Card:**
| key | type | label |
|-----|------|-------|
| twitter_card_type | text | Card Tipi |
| twitter_site | text | Site @handle |
| twitter_creator | text | İçerik Sahibi @handle |
| twitter_title | text | Twitter Default Title |
| twitter_description | textarea | Twitter Default Description |
| twitter_image | image | Twitter Card Görseli (1200x600 px) |

**Doğrulama Kodları:**
| key | type | label |
|-----|------|-------|
| google_site_verification | text | Google Search Console Kodu |
| bing_site_verification | text | Bing Webmaster Kodu |
| yandex_verification | text | Yandex Webmaster Kodu |
| pinterest_verification | text | Pinterest Doğrulama Kodu |

> **UI Önerisi:** SEO grubunu 4 alt sekmeye bölebilirsin: Temel SEO, Open Graph, Twitter Card, Doğrulama Kodları.

### analytics (10 alan)
| key | type | label |
|-----|------|-------|
| google_analytics_id | text | Google Analytics 4 ID (G-XXXXXXXX) |
| google_tag_manager_id | text | Google Tag Manager ID (GTM-XXXXXXX) |
| google_ads_id | text | Google Ads Conversion ID |
| facebook_pixel_id | text | Meta (Facebook) Pixel ID |
| hotjar_id | text | Hotjar Site ID |
| clarity_id | text | Microsoft Clarity ID |
| tiktok_pixel_id | text | TikTok Pixel ID |
| crisp_website_id | text | Crisp Chat Website ID |
| custom_head_scripts | textarea | `<head>` içine özel script |
| custom_body_scripts | textarea | `<body>` sonuna özel script |

### header (9 alan)
| key | type | label |
|-----|------|-------|
| navbar_style_default | text | Varsayılan Navbar Stili (transparent/white) |
| cta_button_text | text | Sağ Üst Buton Metni |
| cta_button_url | url | Sağ Üst Buton Linki |
| cta_button_color | color | Sağ Üst Buton Rengi |
| show_phone_topbar | boolean | Üst Bar'da Telefon Göster |
| show_email_topbar | boolean | Üst Bar'da E-posta Göster |
| show_address_topbar | boolean | Üst Bar'da Adres Göster |
| show_hours_topbar | boolean | Üst Bar'da Saat Göster |
| show_social_navbar | boolean | Navbar'da Sosyal Medya İkonları Göster |

### footer (8 alan)
| key | type | label |
|-----|------|-------|
| footer_description | textarea | Footer Açıklaması |
| footer_logo | image | Footer Logo (varsa ayrı) |
| copyright_text | text | Copyright Metni |
| footer_address | textarea | Footer Adres |
| footer_phone | text | Footer Telefon |
| footer_email | text | Footer E-posta |
| footer_bg_color | color | Footer Arka Plan Rengi |
| show_social_footer | boolean | Footer'da Sosyal Medya Göster |

### integrations (10 alan)
| key | type | label |
|-----|------|-------|
| recaptcha_site_key | text | reCAPTCHA v3 Site Key |
| recaptcha_secret_key | text | reCAPTCHA v3 Secret Key |
| smtp_host | text | SMTP Host |
| smtp_port | text | SMTP Port |
| smtp_username | text | SMTP Kullanıcı Adı |
| smtp_password | text | SMTP Şifre |
| smtp_encryption | text | SMTP Şifreleme (tls/ssl) |
| smtp_from_name | text | Mail Gönderen Adı |
| smtp_from_email | text | Mail Gönderen Adresi |
| notification_emails | textarea | Bildirim E-postaları (virgülle) |

> **Not:** `integrations` grubundaki tüm ayarlar `is_public: false` — public API'den hiçbiri görünmez. `smtp_password` ve `*_secret_key` alanları password input olarak gösterilmeli.

---

## Önerilen Admin Panel Sayfa Yapısı

```
/admin/settings
├── Sidebar veya Tab Navigation
│   ├── Genel          → general
│   ├── İletişim       → contact
│   ├── Harita         → maps
│   ├── Sosyal Medya   → social
│   ├── SEO            → seo (alt sekmeler: Temel, OG, Twitter, Doğrulama)
│   ├── Analitik       → analytics
│   ├── Header         → header
│   ├── Footer         → footer
│   └── Entegrasyonlar → integrations
```

### Kaydet Akışı:
1. Kullanıcı bir gruptaki alanları düzenler
2. "Kaydet" butonuna basar
3. Sadece **değişen** alanlar `PUT /admin/settings` ile gönderilir
4. Başarılı response sonrası toast mesaj göster
5. Gerekirse `POST /admin/settings/clear-cache` butonu ekle (teknik kullanıcılar için)

### Dinamik Form Render:
`label` alanını form label olarak, `type` alanını input bileşeni seçmek için kullan. Backend'den gelen sıralama (`order_index`) form alanlarının sırası olarak kullanılabilir.

---

## Preview Sistemi (Page Builder)

Admin panelden sayfa blokları düzenlenirken önizleme özelliği:

| Method | Endpoint | Açıklama |
|--------|----------|----------|
| `POST` | `/admin/preview` | Önizleme token'ı oluştur |
| `DELETE` | `/admin/preview/{token}` | Önizlemeyi sil |
| `GET` | `/v1/preview/{token}` | Public — frontend fetch (auth yok) |

### POST /admin/preview

```json
// Request
{
  "page_id": 1,
  "blocks": [
    { "type": "hero", "content": { "title": "...", "description": "..." }, "order_index": 0 },
    { "type": "text", "content": { "_width": "half", "title": "...", "body": "..." }, "order_index": 1 }
  ]
}

// Response (201)
{
  "token": "550e8400-e29b-41d4-a716-446655440000",
  "preview_url": "http://localhost:3000/api/preview?token=550e8400...&slug=kalite-politikasi",
  "expires_in": 600
}
```

### Kullanım:
1. Admin panelde "Önizle" butonuna bas → `POST /admin/preview`
2. Response'daki `preview_url`'yi yeni sekmede aç
3. Önizleme 10 dakika geçerli, sonra otomatik silinir
4. İsteğe bağlı: modal kapatılınca `DELETE /admin/preview/{token}` ile temizle
