# Boğaziçi Denizcilik - Backend (Laravel) & Admin Panel (Next.js) Gereksinim Dökümanı (v2) Bu döküman, mevcut Next.js (Frontend) projenizin dinamik veri altyapısını bir **Laravel API**'sine bağlamak ve bu verileri yönetmek için tamamen ayrı bir **Next.js Admin Panel** geliştirmek üzere hazırlanmıştır. *(v2 Güncellemesi: Gelişmiş Setting altyapısı, Pagination standartları, Modüler Page Builder API'leri, Soft Deletes, Caching, Audit Logs, Rate Limiting ve Çok Dilli (i18n) destek notları eklenmiştir.)* > **Çok Dilli (i18n) Altyapı Notu:** Şimdilik v1 aşamasında tek dil (TR) olarak çıkılacaktır. Ancak v2+ versiyonları için i18n (Çoklu dil) planlanıyorsa, veritabanı tablolarında JSON field veya harici translations tablosu yaklaşımı değerlendirilecektir. > **🤖 GitHub Copilot (VS Code) İçin Geliştirme Talimatı (Master Prompt):** > *Laravel Herd ile kendi oluşturduğunuz projeyi VS Code'da açtıktan sonra, Copilot Chat'e (veya Cursor/Cline'a) şu mesajı yazmanız yeterlidir:* > > "Merhaba Copilot, bu projeyi **Laravel 12+** ile geliştireceğiz. Lütfen ana dizindeki **`backend_ve_admin_dokuman.md`** dosyasını dikkatlice baştan sona oku ve mimariyi kavra. > Ardından şu işlemleri benim onayımı alarak **adım adım** kodlamaya başla: > 1. Önce "1. Veritabanı Şeması" bölümündeki tüm tablolar için Laravel Migration, Model ve Factory dosyalarını oluştur. Önemli tablolarda SoftDeletes kullan. Bu adımı bitirince onayımı bekle. > 2. Ardından "REST API" ve "Klasör Mimarisi" bölümüne geç. Kesinlikle spagetti controller yazma. Her modül için sırayla; `FormRequest`, `DTO`, `Action (Service)`, `Repository` ve en son `Controller` ile `api.php` rotalarını oluştur. Response standartlarına ve Caching kurallarına dikkat et. > 3. Her modülü (Örn: Courses, Categories) tek tek kodla ve her modül bitiminde bana bilgi ver. Asla tüm projeyi tek seferde yazmaya çalışma." --- ## 1. Veritabanı Şeması (Laravel Modelleri & Migrations) *(Güvenlik: Kaza eseri veri kayıplarını önlemek için yetki, kurs, kategori ve lead tablolarında `SoftDeletes` kullanılacaktır.)* ### 1.0. `users` & `roles` (Yetkilendirme / Auth) - Laravel'in standart `users` tablosu. Admin panele giriş yapacak personeli temsil eder. - Sisteme **Spatie Permission** paketi kurularak Role ve Yetki altyapısı tanımlanacaktır (Örn: `super-admin`, `editor`). - `SoftDeletes` aktif olmalıdır. ### 1.1. `categories` (Eğitim Kategorileri) - `id` (PK) - `slug` (string, unique) - *Örn: guverte* - `label` (string) - *Örn: Güverte Eğitimleri* - `desc` (text, nullable) - `image` (string, nullable) - *Sadece görsel path'i tutar* - `meta_title` (string, nullable) - *SEO Title* - `meta_description` (text, nullable) - *SEO Description* - `created_at`, `updated_at`, `deleted_at` *(SoftDeletes)* ### 1.2. `courses` (Eğitimler/Kurslar) - `id` (PK) - `category_id` (FK -> categories.id) - `slug` (string, unique) - `title` (string) - `sub` (string, nullable) - *Örn: STCW II/1* - `desc` (text) - *Kısa açıklama* - `long_desc` (longText) - *Detaylı açıklama* - `duration` (string) - *Örn: 5 Gün* - `students` (integer, default: 0) - *Kayıtlı öğrenci sayısı* - `rating` (decimal: 2,1, default: 5.0) - `badge` (string, nullable) - *Örn: Simülatör* - `image` (string, nullable) - *Sadece path tutar* - `price` (string, nullable) - `includes` (json, nullable) - *Fiyata dahil olanlar listesi. Örn: `["Eğitim materyali", "Sertifika ücreti", "İkram"]`* - `requirements` (json, nullable) - *Katılım koşulları/gereksinimler listesi. Örn: `["18 yaşını doldurmuş olmak", "Lise mezunu olmak"]`* - `meta_title` (string, nullable) - *SEO Title* - `meta_description` (text, nullable) - *SEO Description* - `scope` (json, nullable) - *Eğitim kapsamı konu başlıkları dizisi. Örn: `["Ana makine sistemleri", "Yağlama ve soğutma sistemleri", "Yakıt sistemleri"]`* - `standard` (string, nullable) - *Uyum standardı. Örn: `"STCW / IMO Uyumlu"`* - `language` (string, nullable, default: `"Türkçe"`) - *Eğitim dili* - `location` (string, nullable) - *Kursun varsayılan lokasyonu. Örn: `"Kadıköy, İstanbul"`* - `created_at`, `updated_at`, `deleted_at` *(SoftDeletes)* ### 1.3. `course_schedules` (Takvim / Planlanan Eğitimler) - `id` (PK) - `course_id` (FK -> courses.id) - `start_date` (date) - *Örn: 2026-02-24* - `end_date` (date) - *Örn: 2026-02-28* - `location` (string) - *Örn: Kadıköy veya Online* - `quota` (integer) - *Toplam Kontenjan* - `available_seats` (integer) - *Kalan Koltuk (Otomatik `quota - reserved_count` mantığıyla çalışmalı veya admin üzerinden manuel update edilmeli. Proje ilerleyişine göre netleşecek).* - `is_urgent` (boolean, default: false) - *Sınırlı Kontenjan uyarısı* - `created_at`, `updated_at` ### 1.4. `announcements` (Duyurular & Haberler) - `id` (PK) - `slug` (string, unique) - `title` (string) - `category` (string, enum) - *Tutarsızlığı önlemek için Enum kullanılmalı: `announcement` | `news` | `event`* - `excerpt` (text) - `content` (longText) - `image` (string, nullable) - `is_featured` (boolean, default: false) - `meta_title` (string, nullable) - `meta_description` (text, nullable) - `published_at` (timestamp) - *Frontend'deki day/month yerine gerçek tarih tutulmalı* - `created_at`, `updated_at` ### 1.5. `hero_slides` (Ana Sayfa Slider) - `id` (PK) - `label` (string) - *Örn: STCW Sertifikasyonu* - `title` (string) - *Satır başı için \n destekli* - `description` (text) - `image` (string, nullable) - `order` (integer, default: 0) - `is_active` (boolean, default: true) - `created_at`, `updated_at` ### 1.6. `leads` (Ön Kayıtlar / Form Başvuruları) - `id` (PK) - `name` (string) - `phone` (string) - `target_course` (string, nullable) - *İlgilenilen eğitim* - `education_level` (string, nullable) - *Öğrenim durumu* - `subject` (string, nullable) - *İlgilenilen konu (Danışmanlık formu için Örn: stcw, kaptanlik, belge, diger)* - `message` (text, nullable) - *Ziyaretçinin ek mesajı (Danışmanlık formu için)* - `status` (string, default: 'new') - *`new`, `contacted`, `enrolled`, `rejected`* - `notes` (text, nullable) - *Admin notları* - `is_read` (boolean, default: false) - *Admin panelde okunmamışları vurgulamak için* - `source` (string) - *`hero_form` | `contact_form` | `consultation_form` | `whatsapp_widget`* - `utm` (json, nullable) - *`utm_source`, `utm_campaign`, vb.* - `consent_kvkk` (boolean, default: false) - `consent_text_version` (string, nullable) - `created_at`, `updated_at`, `deleted_at` *(SoftDeletes)* ### 1.7. `menus` (Dinamik Menü & Navigasyon Yönetimi) Tüm site üst (Navbar) ve alt (Footer) bağlantılarının, Mega Menü içeriklerinin admin panelinden yönetilebilmesi için. - `id` (PK) - `location` (string) - *Örn: `header_main`, `footer_corporate`, `footer_education`, `footer_quicklinks`* - `label` (string) - *Menüde Gözükecek Metin Örn: "Hakkımızda"* - `url` (string) - *Örn: "/kurumsal/hakkimizda"* - `type` (string, default: 'link') - *`link` (Normal Link) | `mega_menu_education` (Özel Hover Mega Menü) | `mega_menu_calendar` (Takvim Dropdown)* - `parent_id` (integer, nullable) - *Alt menüler için (Self Referencing FK)* - `order` (integer, default: 0) - *Sıralama* - `is_active` (boolean, default: true) - `created_at`, `updated_at` ### 1.8. `comments` (Eğitim ve Blog Yorumları / Soru-Cevap) *Kullanıcıların üye olmadan, sadece Ad, Soyad ve Telefon numarası girerek Eğitimlere veya Duyurulara/Bloglara yorum yapabileceği ve adminlerin cevaplayabileceği sistem.* - `id` (PK) - `commentable_id` (integer) - *Hangi eğitime/duyuruya yapıldı? (Polymorphic Relation)* - `commentable_type` (string) - *`App\\Models\\Course` veya `App\\Models\\Announcement`* - `name_surname` (string) - *Kullanıcının Adı Soyadı* - `phone` (string) - *Kullanıcının Telefon Numarası (Soru sorana ulaşmak gerekirse)* - `body` (text) - *Yorum / Soru metni* - `admin_reply` (text, nullable) - *Admin'in verdiği cevap (Önyüzde Admin Yanıtı olarak gözükecek)* - `is_approved` (boolean, default: false) - *Admin onaylamadan sitede gözükmemeli* - `created_at`, `updated_at`, `deleted_at` *(SoftDeletes)* ### 1.9. `faqs` (Sıkça Sorulan Sorular) *Frontend'deki `/sss` sayfası ve anasayfadaki FAQ bileşeni için. Adminler soru-cevapları kategorili olarak yönetebilir.* - `id` (PK) - `category` (string) - *`egitimler` | `kayit` | `iletisim` (Tab bazlı filtreleme için)* - `question` (text) - *Soru metni* - `answer` (text) - *Cevap metni* - `order` (integer, default: 0) - *Kategori içi sıralama* - `is_active` (boolean, default: true) - *Pasif olanlar önyüzde gösterilmez* - `created_at`, `updated_at` ### 1.10. `guide_cards` (Eğitim Rehberi Kartları) *Frontend'deki `/egitim-rehberi` sayfasındaki kariyer yönlendirme kartları için. Admin panelden yönetilebilir.* - `id` (PK) - `title` (string) - *Örn: "Yeni Başlayanlar", "Yat Kaptanları"* - `description` (text) - *Kart içeriği açıklaması* - `icon` (string) - *Lucide icon adı (Örn: `anchor`, `compass`, `shield`, `briefcase`)* - `color` (string) - *Gradient renk sınıfı (Örn: `from-blue-500 to-blue-700`)* - `link` (string) - *Yönlendirme URL'i (Örn: `/egitimler/stcw`)* - `order` (integer, default: 0) - *Sıralama* - `is_active` (boolean, default: true) - `created_at`, `updated_at` ### 1.11. `settings` (Sistem Ayarları) *Admin panelinde otomatik tab/sekme yapısı kurmak ve public/private yalıtımı sağlamak için güçlendirilmiş yapı. Logo, sosyal medya linkleri gibi statik veriler buradan yönetilir.* - `id` (PK) - `group` (string) - *`general` | `contact` | `social` | `seo` | `forms` | `footer` | `guide`* - `key` (string, unique) - `value` (text/json, nullable) - `type` (string) - *`text` | `textarea` | `image` | `boolean` | `json` | `richtext`* - `is_public` (boolean, default: true) - *Public API'de görünsün mü? (Örn: `hero_form_email` gizli kalmalıdır).* - `created_at`, `updated_at` **Önerilen Settings Key Listesi (Otomatik Seeder ile Girecekler):** - **Genel:** `site_name`, `site_logo`, `footer_logo`, `favicon` - **Anasayfa İçerikleri (Sabit Alanlar):** `home_about_title`, `home_about_text`, `home_about_image_1`, `home_about_image_2`, `home_stats_students`, `home_stats_instructors`, `home_stats_courses` (Anasayfadaki "Biz Kimiz", "Kurum Hakkında" veya istatistik alanlarındaki resim/yazıların yönetimi için). - **İletişim:** `contact_email`, `contact_cc_emails`, `phone_1`, `phone_2`, `whatsapp_phone`, `address`, `google_maps_embed_url`, `working_hours` - **Sosyal Medya (Dinamik Logolar / Linkler):** `instagram_url`, `facebook_url`, `tiktok_url`, `x_url`, `youtube_url`, `linkedin_url` (Bu alanlar boş bırakılırsa önyüzde iconlar gizlenmelidir). - **SEO:** `default_meta_title`, `default_meta_description`, `canonical_base`, `og_default_image`, `robots_indexing_enabled` - **Formlar / KVKK / Kampanya:** `lead_notify_email`, `kvkk_text`, `privacy_policy_url`, `newsletter_title`, `newsletter_desc` (E-bülten ve "Sana özel kampanyalar" kutusundaki metinler). - **Eğitim Rehberi:** `guide_page_title`, `guide_page_subtitle`, `guide_cta_title`, `guide_cta_text`, `guide_cta_button_text`, `guide_cta_button_url` (Eğitim Rehberi sayfasındaki başlık, alt metin ve CTA alanlarının yönetimi). - **Danışmanlık:** `consultation_page_title`, `consultation_page_subtitle`, `consultation_form_title` (Danışmanlık sayfasının başlık ve açıklama alanlarının yönetimi). --- ## 2. Laravel REST API Uç Noktaları (Endpoints) & Standartları **Cevap (Response) Format Standardı:** Frontend tarafının hızlı ilerlemesi için tüm başarılı API listeleme talepleri paginate ve metadata içermeli, Laravel Resource üzerinden standartlaştırılmalıdır. - Liste endpoint'leri: `{ "data": [], "meta": { "total": 0 }, "links": { } }` - Tekil endpoint'ler: `{ "data": { } }` **Parametrik Arama, Filtreleme, Sıralama:** - `GET /api/v1/courses?category=guverte&search=stcw&sort=title&page=1` - `GET /api/v1/announcements?category=news&featured=1&sort=-published_at&page=1` ### Public API (Frontend İçin - `api/v1/...`) *(Performans için aktif olan sık kullanılan Public GET endpoint'leri **Laravel Cache / Redis** arkasında çalıştırılmalıdır. Veri Admin Panel'den güncellenince Cache Event ile temizlenmelidir.)* - `GET /api/v1/settings` -> `is_public=true` olan ayarları döner. - `GET /api/v1/hero-slides` -> Aktif slider içeriklerini sıralı getirir. - `GET /api/v1/menus` -> Header ve Footer navigasyon ağacını hiyerarşik getirir. - `GET /api/v1/categories` -> Kategorileri listeler. - `GET /api/v1/courses` -> Eğitimleri listeler. - `GET /api/v1/courses/{slug}` -> Tekil eğitim detayı. - `GET /api/v1/schedules` -> Yaklaşan takvim eğitimlerini getirir. (Tarihe göre sıralı) - `GET /api/v1/announcements` -> Duyuruları (featured olanlar dahil) getirir. - `GET /api/v1/announcements/{slug}` -> Tekil duyuru detayı. - `GET /api/v1/comments/{type}/{id}` -> Bir kursun veya blogun onaylanmış (`is_approved=true`) yorumlarını ve admin cevaplarını getirir. - `POST /api/v1/comments` -> Ziyaretçiden yeni yorum/soru kaydı alır (Spam/Rate Limiting zorunlu). - `GET /api/v1/faqs` -> Aktif SSS verilerini kategorili olarak getirir. `?category=egitimler` filtresi desteklenmeli. - `GET /api/v1/guide-cards` -> Eğitim Rehberi kartlarını sıralı getirir. - `GET /api/v1/pages/{slug}` -> Page builder bloklarını sırayla (`order_index`) getirir. *(Sadece `/page/` altındaki dinamik sayfalar için)* - `POST /api/v1/leads` -> Ön kayıt formu alımı. `source` alanı ile form kaynağı (`hero_form`, `contact_form`, `consultation_form`) belirlenir. *(Spam koruması için IP bazlı Rate Limiting - Throttle uygulanmalıdır. Dakikada maks 2-3 gibi)* - `GET /api/v1/sitemap-data` -> Frontend'in dinamik `sitemap.xml` oluşturması için tüm public slug'ları ve `updated_at` tarihlerini döner. *(Bkz: Bölüm 7.4)* ### Protected API (Admin Panel İçin - `api/admin/...`) Tüm yetkili işlemler burada yalıtılmıştır. - `POST /api/admin/login` -> Bearer token döndürür (Sanctum/Passport). - `GET /api/admin/me` -> Giriş yapan admin detaylarını + Spatie Permission rollerini/izinlerini döner. - `POST /api/admin/uploads` -> Multipart/form-data kabul eder. Standart resim yükleme ucudur. DB'ye URL değil **path** kaydeder. Response: `{ "path": "uploads/...", "url": "https://.../uploads/..." }` - Modüller için tüm standart `POST` (Oluşturma), `PUT/PATCH` (Güncelleme), `DELETE` (Silme) uçları. - Menü Yönetimi: - `CRUD /api/admin/menus` -> Menü ekleme ve ağaç dökümü - `POST /api/admin/menus/reorder` -> Sürükle-Bırak sonrası hiyerarşiyi (parent_id ve order) toplu güncelleme - SSS (FAQ) Yönetimi: - `CRUD /api/admin/faqs` -> Soru ekleme, düzenleme, silme, listeleme - Eğitim Rehberi Kartları: - `CRUD /api/admin/guide-cards` -> Kart ekleme, düzenleme, silme, listeleme - Page Builder Admin uçları: - `CRUD /api/admin/pages` - `CRUD /api/admin/pages/{id}/blocks` - `POST /api/admin/pages/{id}/blocks/reorder` -> Sürükle bırak ile sıra (`order_index`) güncelleme. --- ## 3. Laravel Katmanlı Mimari (Repository Pattern) Uygulama Standartları Backend kodlanırken kesinlikle **Spagetti Controller** (Controller içine direkt `Course::create()` yazmak) kullanılmayacaktır. Tüm iş mantığı ve veritabanı sorguları şu katmanlara ayrılmalıdır: **Önerilen Devasa (Enterprise) Klasör Mimarisi (`app/`):** ```text app/ ├── Http/ │ ├── Controllers/ │ │ └── Api/ │ │ └── CourseController.php # HTTP İsteğini alır, DTO'yu oluşturup Action'a yollar. Geriye Response döner. │ ├── Requests/ │ │ └── StoreCourseRequest.php # Gelen verilerin validasyon zorunluluklarını (required, string) yapar. │ └── Resources/ │ └── CourseResource.php # {YENİ} Frontend'e gidecek JSON formatını filtreler ve standartlaştırır (Presenter). ├── DTOs/ │ └── CourseData.php # Validasyonu geçmiş temiz veriyi, tiplendirilmiş Nesneye (DTO) dönüştürür. ├── Actions/ (veya Services/) │ └── Course/ │ └── CreateCourseAction.php # Tüm "İş Mantığı". İndirim hesapla, Event fırlat, Repository'e yolla. ├── Repositories/ │ ├── Contracts/ │ │ └── CourseRepositoryInterface.php # Sınırlar ve Kurallar (Interface) │ └── Eloquent/ │ └── CourseRepository.php # Veritabanı (DB) sorguları sadece buradadır (Course::create()). ├── Models/ │ └── Course.php # Tablo yapısı, İlişkiler (Relations) ├── Enums/ │ └── CourseStatus.php # Güvenli Sabitler ├── Events/ │ └── CourseCreatedEvent.php # Asenkron Olaylar (Decoupling için) -> Cache temizleme vb. burada ateşlenir. ├── Listeners/ │ └── NotifySubscribersListener.php # Olayı dinleyen arka plan işlemleri ├── Policies/ │ └── CoursePolicy.php # Yetki ve Rol kontrolleri (Örn: Yetkisiz kişi kurs silemez) ├── Exceptions/ │ └── CourseFullException.php # Domain'e özel hata sınıfları (400) ``` **Kusursuz (Ultimate) Veri Akış Yönü:** `Route` ➔ `Middleware (Auth)` ➔ `Policy (Yetki)` ➔ `FormRequest (Validasyon)` ➔ `Controller` ➔ `DTO` ➔ `Action` ➔ `Repository (Interface)` ➔ `Model` ➔ `DB` *(İşlem Başarılıysa)* ➔ `Action => Event Fırlatır / Activity Log Atılır` *(Controller Çıkışı)* ➔ `API Resource (JSON Formatlama)` ➔ `Next.js FrontEnd` **Audit Log / Kullanıcı İşlem Kayıtları Notu:** Sisteme yetkili girişler yapılacağı için (Super Admin, Editor vs) veri güncellemelerini, silmeleri (SoftDelete edilen datalar) izlemek amacıyla projeye `spatie/laravel-activitylog` paketi kurulması, oluşan Transaction'ların tutulması önerilir. --- ## 4. Next.js Admin Panel Mimarisi Önerisi Admin Paneli tamamen ayrı bir Next.js projesi olarak (Örn: `admin.bogazicidenizcilik.com` veya `localhost:3001` portunda) kurulmalıdır. ### **Mimari Prensip (Katmanlı Mimari - Layered Architecture):** Kodların tek bir klasöre yığılmasını önlemek için Frontend kodları işlevselliğe göre ayrılmalıdır. Örnek `src/` mimarisi: - `src/app/`: Sadece sayfalar (Routing) ve sayfa Layout'ları. - `src/components/`: Ortak kullanılan UI elementleri (Button, Input, Table, **Ortak ImageUpload Bileşeni**). - `src/features/`: Modül bazlı klasörleme (Örn: `features/courses/components`, `features/courses/api`, `features/courses/types`). - `src/lib/`: Axios instance, yardımcı fonksiyonlar. ### Önerilen Klasör Dizilimi (`src/app/` Route Alanı): ```text src/app/ ├── (auth)/ │ └── login/page.tsx # Giriş ekranı (Kullanıcı Adı, Şifre -> Laravel Sanctum Token) ├── (dashboard)/ │ ├── layout.tsx # Sol Sidebar ve Üst Header kapsayıcısı (Role-based menu gösterimi) │ ├── page.tsx # Dashboard Özeti (İstatistik kartları: Toplam Öğrenci, Yeni Formlar) ... ``` ### Tüm Admin Modülleri ve Ekran Detayları #### 4.1. Kategoriler (`/categories`) - **`page.tsx`:** Kategori Tablosu (Resim, Kategori Adı, İşlemler (Düzenle/Sil)). - **`[id]/page.tsx` (Ekleme / Düzenleme Formu):** - `label` *(Text Input)* - Kategori Adı - `slug` *(Text Input)* - (Girilen isimden otomatik slug yaratılmalı) - `desc` *(Textarea)* - Kısa Tanıtım - `image` *(Upload Component)* - `POST /api/admin/uploads` tetikleyecek tek kullanımlık standart bileşen - **SEO Alanı:** `meta_title`, `meta_description` *(Text Input)* #### 4.2. Eğitimler (`/courses`) - **`page.tsx`:** Eğitimler Tablosu (Kategorisine göre filtrelenebilir, Öğrenci Sayısı vs.). - **`[id]/page.tsx` (Ekleme / Düzenleme Formu):** - **Genel Bilgiler:** - `title`, `sub`, `category_id`, `price`, `duration`, `badge` - **İçerik Editörü:** - `desc` *(Textarea)* - `longDesc` *(Rich Text Editor - CKEditor/Quill/Notion-stile Editor)* - `image` *(Upload Component)* - **Dinamik Diziler (Field Arrays / Repeaters):** - `includes` *(Dynamic Input Array)* - "Fiyata Dahil Olanlar" (+) - `requirements` *(Dynamic Input Array)* - "Kayıt Şartları" (+) - **SEO Alanı:** `meta_title`, `meta_description` *(Text Input)* #### 4.3. Eğitim Takvimi / Planlama (`/schedules`) - **`page.tsx`:** Takvim Tablosu (Kurs Adı, Başlangıç, Bitiş, Kontenjan). - **`[id]/page.tsx` (Ekleme / Düzenleme Formu):** - `course_id`, `start_date`, `end_date`, `location`, `quota`, `available_seats` - `is_urgent` *(Switch / Checkbox)* - "Son 3 Gün" uyarı ateşleyicisi #### 4.4. Duyurular ve Haberler (`/announcements`) - **`page.tsx`:** Olayların Tablosu. - **`[id]/page.tsx` (Ekleme / Düzenleme Formu):** - `title`, `category` (Seçim ile), `excerpt`, `content` (RTE), `image` (Upload), `meta_title`, `meta_description` - `published_at` *(Date/Time Picker)* - İleri tarihli yayınlanma opsiyonu - `is_featured` *(Switch)* - "Ana Sayfada Manşet Yap" onay kutusu #### 4.5. Ön Kayıt Başvuruları (CRM) (`/leads`) - **`page.tsx`:** Form başvuruları listesi. **`is_read = false` olan kayıtlar kalın (bold) veya fosforlu arka planla ayırt edici gösterilmelidir.** - **`[id]/page.tsx` (Görüntüleme Müşteri Detayı):** - Gelen veriler: *Adı, Telefon, Durumu, İlgilendiği Eğitim, Kaynak (Source), UTMEketleri, KVKK Onay Vrs.* (Salt Okunur - Read/Only). - Yalnızca Tıklandığında backend'e PATCH isteği atılıp `is_read = true` yapılır. - Admin işlemleri: - `status` *(Select)* - (Yeni, Arandı, Kayıt Oldu, İptal) - `notes` *(Textarea)* - Admin/Müşteri Temsilcisi iç notları. Form POST ile güncellenir. #### 4.6. Menü ve Navigasyon Yönetimi (`/menus`) - **`page.tsx`:** Menü lokasyonlarına (`header_main`, `footer_corporate`, `footer_education`, vb.) göre sekmeli (tab) bir liste. Her lokasyon için alt alta ağaç (tree) görünümlü kayıtlar. Sürükle-bırak (Drag & Drop) ile `POST /api/admin/menus/reorder` tetiklenerek sıralama ve parent/child ilişkisi hızlıca kurulabilmeli. - **`[id]/page.tsx` (Ekleme / Düzenleme):** - `location` *(Select)* - Header Ana Menü mü Yoksa Footer mı? - `label` *(Text Input)* - "Eğitimler" - `url` *(Text Input)* - "/egitimler" - `type` *(Select)* - Normal Link mi (`link`), Eğitim Mega Menüsü mü (`mega_menu_education`), Takvim mi (`mega_menu_calendar`) - `parent_id` *(Select)* - Bir ana menünün altına eklenecekse o ana menü seçilir. - `is_active` *(Switch)* #### 4.7. Yorum / Soru-Cevap Yönetimi (`/comments`) - **`page.tsx`:** Kullanıcılardan (üye olmadan) Eğitim ve Bloglara gelen tüm soruların/yorumların düştüğü ekran. `is_approved = false` olanlar (yeni gelenler) belirgin şekilde listelenir. - **`[id]/page.tsx` (Yorum Onay ve Yanıtlama):** - Gelen veriler: *Adı Soyadı, Telefon Numarası, Yorum Yapılan İçerik (Kurs Adı vs), Yorum Metni* (Read-Only). - `admin_reply` *(Textarea)* - Yorum/soruyu cevaplamak için adminin dolduracağı alan. - `is_approved` *(Switch)* - Yorumun sitede herkes tarafından gözüküp gözükmeyeceği. #### 4.8. SSS / Sıkça Sorulan Sorular Yönetimi (`/faqs`) - **`page.tsx`:** FAQ Tablosu (Kategori, Soru, Aktif/Pasif durumu). Kategoriye göre filtrelenebilir. - **`[id]/page.tsx` (Ekleme / Düzenleme Formu):** - `category` *(Select)* - `egitimler` | `kayit` | `iletisim` - `question` *(Textarea)* - Soru metni - `answer` *(Textarea / Rich Text)* - Cevap metni - `order` *(Number Input)* - Kategori içi sıralama - `is_active` *(Switch)* - Aktif/Pasif #### 4.9. Eğitim Rehberi Kartları Yönetimi (`/guide-cards`) - **`page.tsx`:** Rehber kartlarının listesi (Başlık, Icon, Link, Sıra). - **`[id]/page.tsx` (Ekleme / Düzenleme Formu):** - `title` *(Text Input)* - Kart başlığı (Örn: "Yeni Başlayanlar") - `description` *(Textarea)* - Açıklama metni - `icon` *(Select)* - Lucide icon seçimi (`anchor`, `compass`, `shield`, `briefcase` vb.) - `color` *(Text Input / Color Picker)* - Gradient renk sınıfı - `link` *(Text Input)* - Yönlendirme URL'i - `order` *(Number Input)* - Sıralama - `is_active` *(Switch)* #### 4.10. Sitenin Genel Ayarları (`/settings`) Bu tek bir sayfada çalışır: - Sayfa ilk açıldığında `GET /api/admin/settings` ile tüm satırları çeker. - `group` verisine göre yatay ya da dikey Tabs (Sekmeler) oluşturur (Genel, Anasayfa, İletişim, Sosyal Medya, SEO, Formlar, Eğitim Rehberi, Danışmanlık). - **Anasayfa Sekmesi:** Anasayfadaki "Neden Biz", "Biz Kimiz", info/görsel alanlarındaki başlıklar (`home_about_title`), metinler (`home_about_text`) ve resimlerin (`home_about_image_1`) yönetimi. - **Sosyal Medya Sekmesi:** Tüm hesapların (Instagram, Facebook, Tiktok, LinkedIn vb.) linkleri buraya girilir. Frontend, boş olmayan değerleri render eder. - **Eğitim Rehberi Sekmesi:** Eğitim rehberi sayfasının başlık, alt metin ve CTA (Call to Action) alanlarının yönetimi. - **Danışmanlık Sekmesi:** Danışmanlık sayfasının başlık ve açıklama metinleri. - `type` verisine göre ekranda Text Input, Textarea veya Toggle Switch render eder. Kaydederken array olarak tek bir PATCH isteğinde sunucuya yollar. --- ## 5. Mevcut Frontend Projesi (Boğaziçi) Entegrasyon Adımları Backend ve Admin Panel hazır olduğunda, mevcut statik yapınızda şu işlemler gerçekleştirilecektir: 1. **Çevresel Değişkenler:** `.env.local` içine `NEXT_PUBLIC_API_URL=http://api.bogazici.test/api/v1` eklenmeli. Yüklenen resimleri parse edebilmek için `NEXT_PUBLIC_ASSET_URL=http://api.bogazici.test` konulmalı. 2. **Data Fetching:** - Statik `src/data/*.ts` dosyaları silinmeli. - Tüm sayfalarda `fetch` kullanılarak (veya Axios) ISR yapısıyla veriler çekilmeli. - *Örnek:* `const res = await fetch(\`\${process.env.NEXT_PUBLIC_API_URL}/courses\`, { next: { revalidate: 3600 } });` 3. **Form Gönderimi:** Hero'daki form submit edildiğinde veriler `POST /api/v1/leads` ucuna JSON olarak yollanmalı. --- ## 6. Dinamik Sayfalar İçin Headless Page Builder (`/page/` Rotası) > **Kapsam Notu:** Page Builder sistemi **yalnızca** `/page/` rotası altında oluşturulan dinamik sayfalar için kullanılacaktır. Kurumsal sayfalar (`/kurumsal/hakkimizda`, `/kurumsal/vizyon-misyon`, vb.) ve `/danismanlik`, `/egitim-rehberi`, `/sss` gibi özel tasarımlı sayfalar frontend'de statik bileşenler olarak kalacak ve verilerini kendi API endpoint'lerinden veya `settings` tablosundan çekeceklerdir. Admin panelden yeni landing page'ler, kampanya sayfaları veya özel içerik sayfaları oluşturmak için **Modüler Blok Sistemi** kullanılacaktır. ### Mevcut Frontend (Boğaziçi Denizcilik) Tarafında Okunması **Örnek `src/app/page/[slug]/page.tsx` Kullanımı:** ```tsx export default async function DynamicPage({ params }: { params: { slug: string } }) { // 1. Laravel'den sayfanın aktif bloklarını çek const page = await fetch(`.../api/v1/pages/${params.slug}`).then(r => r.json()); return (
{/* 2. Gelen blokları (Lego parçalarını) sırası ve tipine göre render et */} {page.blocks.map((block) => { switch (block.type) { case 'hero': return ; case 'stats_grid': return ; case 'text_image': return ; default: return null; } })}
); } ``` > **Özet Tavsiye:** Geliştirme süresi uzasa da, bir kere kurulduğunda kodlamaya bir daha dokunmadan şirketin sayısız ve benzersiz tasarımda yeni sayfalar veya landing page'ler üretmesini sağlar. Endüstri standardı bir çözümdür. --- ## 7. SEO & Yapısal Veri (Structured Data) Standartları Sitenin arama motorlarında üst sıralarda yer alabilmesi için backend API'nin aşağıdaki SEO gereksinimlerini eksiksiz karşılaması gerekmektedir. ### 7.1. Meta Alanları (Her Modülde Zorunlu) Aşağıdaki tablolarda `meta_title` ve `meta_description` alanları mevcuttur ve **zorunlu olarak** doldurulmalıdır: - `categories` — ✅ `meta_title`, `meta_description` - `courses` — ✅ `meta_title`, `meta_description` - `announcements` — ✅ `meta_title`, `meta_description` > **Kural:** Admin panelde bu alanlar boş bırakıldığında, `title` veya `excerpt` alanından otomatik üretilmelidir (Frontend veya Backend tarafında fallback mantığı ile). ### 7.2. OpenGraph Görsel Desteği Sosyal medyada paylaşıldığında güzel bir önizleme kartı oluşturabilmek için: - `courses.image` ve `announcements.image` alanları aynı zamanda **OG Image** olarak kullanılacaktır. - Frontend'de `generateMetadata` fonksiyonunda bu görseller `openGraph.images` altına eklenmelidir. - Görseller **minimum 1200x630px** boyutunda olmalıdır. Admin panelde resim yüklerken bu uyarı gösterilmelidir. ### 7.3. JSON-LD Yapısal Veri Şemaları (Schema.org) Google Rich Snippets, Knowledge Panel ve zengin arama sonuçları için aşağıdaki JSON-LD blokları frontend'de render edilmelidir: #### Ana Sayfa (`/`) ```json { "@context": "https://schema.org", "@type": "EducationalOrganization", "name": "Boğaziçi Denizcilik", "url": "https://www.bogazicidenizcilik.com.tr", "logo": "...", "description": "...", "address": { "@type": "PostalAddress", ... }, "contactPoint": { "@type": "ContactPoint", ... }, "sameAs": ["instagram", "facebook", "youtube", ...] } ``` *(Mevcut frontend'de zaten var ✅ — Veriler settings API'den çekilmeli)* #### Eğitim Detay Sayfası (`/egitimler/{kategori}/{slug}`) ```json { "@context": "https://schema.org", "@type": "Course", "name": "STCW Temel Güvenlik (BST)", "description": "...", "provider": { "@type": "Organization", "name": "Boğaziçi Denizcilik", "sameAs": "https://www.bogazicidenizcilik.com.tr" }, "hasCourseInstance": { "@type": "CourseInstance", "courseMode": "onsite", "duration": "P5D", "location": { "@type": "Place", "name": "Kadıköy, İstanbul" } } } ``` > **Backend Notu:** API'den `GET /api/v1/courses/{slug}` response'unda `json_ld` alanı opsiyonel olarak döndürülebilir veya frontend tarafında oluşturulabilir. #### Duyuru Detay Sayfası (`/duyurular/{slug}`) ```json { "@context": "https://schema.org", "@type": "NewsArticle", "headline": "...", "datePublished": "2026-02-15", "author": { "@type": "Organization", "name": "Boğaziçi Denizcilik" }, "image": "...", "publisher": { "@type": "Organization", "name": "Boğaziçi Denizcilik", "logo": "..." } } ``` #### SSS Sayfası (`/sss`) — **FAQPage Schema (Çok Önemli)** ```json { "@context": "https://schema.org", "@type": "FAQPage", "mainEntity": [ { "@type": "Question", "name": "Eğitimleriniz hangi kurumlar tarafından onaylıdır?", "acceptedAnswer": { "@type": "Answer", "text": "Tüm eğitimlerimiz Ulaştırma ve Altyapı Bakanlığı onaylıdır..." } } ] } ``` > ⚠️ **Google FAQPage Rich Result**: SSS sayfasında bu şema kullanılırsa arama sonuçlarında soru-cevaplar **doğrudan** gösterilir. Bu `GET /api/v1/faqs` endpoint'inden dönen verilerle frontend'de dinamik olarak oluşturulmalıdır. #### Tüm Sayfalarda — **BreadcrumbList Schema** ```json { "@context": "https://schema.org", "@type": "BreadcrumbList", "itemListElement": [ { "@type": "ListItem", "position": 1, "name": "Anasayfa", "item": "https://..." }, { "@type": "ListItem", "position": 2, "name": "Eğitimler", "item": "https://.../egitimler" }, { "@type": "ListItem", "position": 3, "name": "STCW Temel Güvenlik" } ] } ``` ### 7.4. Dinamik Sitemap (API Destekli) Mevcut `sitemap.ts` statik datayla çalışmaktadır. Backend hazır olduğunda: - `GET /api/v1/sitemap-data` → Tüm public slug'ları, `updated_at` tarihleriyle döndüren özel endpoint. Frontend `sitemap.ts` bunu kullanarak dinamik sitemap oluşturacak. - Sitemap `lastModified` alanları gerçek `updated_at` tarihlerinden beslenmelidir (şu an tüm sayfalarda `new Date()` kullanılıyor). - Yeni kurs/duyuru/sayfa eklendiğinde sitemap otomatik olarak güncellenecektir. **Önerilen endpoint response yapısı:** ```json { "courses": [{ "slug": "stcw-temel-guvenlik", "kategori": "stcw", "updated_at": "2026-02-15" }], "announcements": [{ "slug": "kayitlar-basladi", "updated_at": "2026-02-10" }], "pages": [{ "slug": "kampanya-bahar-2026", "updated_at": "2026-02-01" }] } ``` ### 7.5. Canonical URL'ler - Tüm sayfalarda `` bulunmalıdır. Mevcut frontend'de `alternates.canonical` zaten desteklenmekte. ✅ - Backend API'den gelen slug'lar ile frontend URL yapısı **birebir eşleşmelidir**. - `courses` slug'ları: `/egitimler/{kategoriSlug}/{courseSlug}` - `announcements` slug'ları: `/duyurular/{slug}` ### 7.6. Hızlı SEO Kontrol Listesi (Checklist) | Öğe | Durum | Açıklama | |---|---|---| | `` tag — Her sayfada benzersiz | ✅ | `generateMetadata` ile dinamik | | `<meta description>` — Her sayfada benzersiz | ✅ | DB'den `meta_description` alanı | | `<link rel="canonical">` | ✅ | `alternates.canonical` ile | | OpenGraph tags (og:title, og:description, og:image) | ✅ | Dinamik sayfalarda var | | Twitter Card tags | ✅ | Layout'ta global tanımlı | | `robots.txt` | ✅ | `/api/` bloklanmış | | XML Sitemap | ✅ | Dinamik hale getirilecek (7.4) | | JSON-LD EducationalOrganization | ✅ | Ana sayfada mevcut | | JSON-LD Course | ⚠️ | Detay sayfasına eklenmeli | | JSON-LD NewsArticle | ⚠️ | Duyuru detay sayfasına eklenmeli | | JSON-LD FAQPage | ❌ | SSS sayfasına eklenmeli | | JSON-LD BreadcrumbList | ❌ | Tüm sayfalara eklenmeli | | `<html lang="tr">` | ✅ | Layout'ta mevcut | | Semantic HTML (h1, h2, article, nav) | ✅ | Tüm sayfalarda uygulanmış | | Image alt attributes | ✅ | Görsellerde title kullanılıyor | | Lazy loading images | ✅ | İlk 6 eager, geri kalan lazy | | `generateStaticParams` (SSG) | ✅ | Tüm dinamik rotalarda var | | ISR / Revalidate | ⚠️ | API entegrasyonunda `revalidate` eklenecek | > **Öncelik Sırası:** FAQPage schema → BreadcrumbList schema → Course JSON-LD → NewsArticle JSON-LD → Dinamik Sitemap --- ## 8. Backend Uygulama Durumu (Implementation Status) > *Bu bölüm, yukarıdaki gereksinimlere göre Laravel backend'de yapılan tüm implementasyonları belgelemektedir.* ### 8.1. Veritabanı & Model Katmanı | Bileşen | Sayı | Durum | Detay | |---------|------|-------|-------| | Migration | 22 | ✅ | users, cache, jobs, permission_tables, activity_log (×3), personal_access_tokens, soft_deletes_users, categories, courses, course_schedules, announcements, hero_slides, leads, menus, comments, faqs, guide_cards, settings, pages, page_blocks | | Model | 14 | ✅ | User, Category, Course, CourseSchedule, Announcement, HeroSlide, Lead, Menu, Comment, Faq, GuideCard, Setting, Page, PageBlock | | Factory | 13 | ✅ | Tüm modeller için (User dahil) | | Enum | 8 | ✅ | AnnouncementCategory, FaqCategory, LeadSource, LeadStatus, MenuLocation, MenuType, SettingGroup, SettingType | | Seeder | 5 | ✅ | DatabaseSeeder, RolePermissionSeeder, AdminUserSeeder, SettingSeeder, RoleSeeder (artık kullanılmıyor) | ### 8.2. Katmanlı Mimari (Repository Pattern) Bileşenleri Dökümanın 3. bölümünde belirtilen mimari tam olarak uygulanmıştır: ``` Route ➔ Middleware (Auth) ➔ Policy (Yetki) ➔ FormRequest (Validasyon) ➔ Controller ➔ DTO ➔ Action ➔ Repository (Interface) ➔ Model ➔ DB ``` | Katman | Sayı | Kapsam | |--------|------|--------| | Repository Interface | 13 | BaseRepositoryInterface + 12 modül | | Repository Eloquent | 13 | BaseRepository + 12 modül | | DTO (Data Transfer Object) | 11 | Tüm CRUD modülleri | | Action (Service) | 34 | Create/Update/Delete × 11 modül + UpdateSettingsAction | | FormRequest | 25 | Store/Update × 11 modül + LoginRequest + ReorderMenuRequest + UpdateSettingsRequest | | API Resource | 13 | Tüm modüller + PageBlockResource | | Controller | 28 | 13 Public (V1) + 15 Admin | | Policy | 11 | Category, Course, CourseSchedule, Announcement, HeroSlide, Lead, Menu, Comment, Faq, GuideCard, Page | ### 8.3. Yetkilendirme & Permission Sistemi (Spatie Permission v7) #### Roller | Rol | Açıklama | |-----|----------| | `super-admin` | Tüm 48 permission'a sahip | | `editor` | Silme (`delete-*`) hariç 36 permission'a sahip | #### Permission Yapısı (12 Modül × 4 Aksiyon = 48 Permission) | Modül | `view-*` | `create-*` | `update-*` | `delete-*` | |-------|----------|------------|------------|------------| | category | ✅ | ✅ | ✅ | ✅ | | course | ✅ | ✅ | ✅ | ✅ | | schedule | ✅ | ✅ | ✅ | ✅ | | announcement | ✅ | ✅ | ✅ | ✅ | | hero-slide | ✅ | ✅ | ✅ | ✅ | | lead | ✅ | ✅ | ✅ | ✅ | | menu | ✅ | ✅ | ✅ | ✅ | | comment | ✅ | ✅ | ✅ | ✅ | | faq | ✅ | ✅ | ✅ | ✅ | | guide-card | ✅ | ✅ | ✅ | ✅ | | setting | ✅ | ✅ | ✅ | ✅ | | page | ✅ | ✅ | ✅ | ✅ | > **Not:** `editor` rolü `delete-*` permission'larından hariç tutulmuştur. Tüm policy dosyaları `hasPermissionTo()` ile çalışmaktadır (rol kontrolü değil, permission kontrolü). ### 8.4. API Rotaları Toplam **97 rota** kayıtlıdır. #### Public API — `GET /api/v1/...` | Endpoint | Controller | Açıklama | |----------|-----------|----------| | `GET /api/v1/categories` | CategoryController@index | Kategorileri listeler | | `GET /api/v1/categories/{slug}` | CategoryController@show | Tekil kategori | | `GET /api/v1/courses` | CourseController@index | Eğitimleri listeler | | `GET /api/v1/courses/{slug}` | CourseController@show | Tekil eğitim detayı | | `GET /api/v1/schedules` | ScheduleController@index | Takvim eğitimleri | | `GET /api/v1/schedules/upcoming` | ScheduleController@upcoming | Yaklaşan eğitimler | | `GET /api/v1/schedules/{id}` | ScheduleController@show | Tekil takvim kaydı | | `GET /api/v1/announcements` | AnnouncementController@index | Duyurular | | `GET /api/v1/announcements/{slug}` | AnnouncementController@show | Tekil duyuru | | `GET /api/v1/hero-slides` | HeroSlideController@index | Aktif slider | | `POST /api/v1/leads` | LeadController@store | Ön kayıt formu (Rate Limit: 3/dk) | | `GET /api/v1/comments/{type}/{id}` | CommentController@index | Onaylı yorumlar | | `POST /api/v1/comments` | CommentController@store | Yeni yorum (Rate Limit: 3/dk) | | `GET /api/v1/menus/{location}` | MenuController@index | Menü ağacı | | `GET /api/v1/faqs` | FaqController@index | SSS listesi | | `GET /api/v1/faqs/{category}` | FaqController@index | Kategoriye göre SSS | | `GET /api/v1/guide-cards` | GuideCardController@index | Rehber kartları | | `GET /api/v1/settings` | SettingController@index | Public ayarlar (`is_public=true`) | | `GET /api/v1/pages/{slug}` | PageController@show | Dinamik sayfa (Page Builder) | | `GET /api/v1/sitemap-data` | SitemapController@index | Sitemap verileri | #### Admin API — `POST|GET|PUT|DELETE /api/admin/...` (Sanctum Auth) | Endpoint | Controller | Açıklama | |----------|-----------|----------| | `POST /api/admin/login` | AuthController@login | Giriş → Bearer Token | | `GET /api/admin/me` | AuthController@me | Giriş yapan admin bilgisi | | `POST /api/admin/logout` | AuthController@logout | Çıkış | | `POST /api/admin/uploads` | UploadController@store | Dosya yükleme | | `CRUD /api/admin/categories` | AdminCategoryController | apiResource | | `CRUD /api/admin/courses` | AdminCourseController | apiResource | | `CRUD /api/admin/schedules` | AdminScheduleController | apiResource | | `CRUD /api/admin/announcements` | AdminAnnouncementController | apiResource | | `CRUD /api/admin/hero-slides` | AdminHeroSlideController | apiResource | | `CRUD /api/admin/leads` | AdminLeadController | apiResource (store hariç) | | `POST /api/admin/menus/reorder` | AdminMenuController@reorder | Menü sıralaması | | `CRUD /api/admin/menus` | AdminMenuController | apiResource | | `CRUD /api/admin/comments` | AdminCommentController | apiResource (store hariç) | | `CRUD /api/admin/faqs` | AdminFaqController | apiResource | | `CRUD /api/admin/guide-cards` | AdminGuideCardController | apiResource | | `GET /api/admin/settings` | AdminSettingController@index | Tüm ayarlar | | `GET /api/admin/settings/group/{group}` | AdminSettingController@group | Grup bazlı | | `PUT /api/admin/settings` | AdminSettingController@update | Toplu güncelleme | | `CRUD /api/admin/pages` | AdminPageController | apiResource | | `POST /api/admin/pages/{page}/blocks/reorder` | AdminBlockController@reorder | Blok sıralaması | | `CRUD /api/admin/pages/{page}/blocks` | AdminBlockController | Nested apiResource | ### 8.5. Cache & Event Sistemi | Bileşen | Dosya | Açıklama | |---------|-------|----------| | Event | `app/Events/ModelChanged.php` | Tüm CRUD Action'larda dispatch edilir | | Listener | `app/Listeners/ClearModelCache.php` | ModelChanged event'ini dinler, ilgili cache key'lerini temizler | **Cache Uygulanan Repository'ler:** | Repository | Cache Key | TTL | Açıklama | |-----------|-----------|-----|----------| | SettingRepository | `settings:public` | 1 saat | Public ayarlar | | HeroSlideRepository | `hero_slides:active` | 1 saat | Aktif slider | | GuideCardRepository | `guide_cards:active` | 1 saat | Aktif rehber kartları | | MenuRepository | `menus:{location}` | 1 saat | Lokasyona göre menü | | FaqRepository | `faqs:{category}` | 1 saat | Kategoriye göre SSS | > Admin panelden veri güncellendiğinde `ModelChanged` event'i fırlatılır ve `ClearModelCache` listener ilgili cache key'lerini otomatik olarak temizler. ### 8.6. Güvenlik & Middleware | Özellik | Durum | Detay | |---------|-------|-------| | Sanctum Token Auth | ✅ | Admin API koruması (`auth:sanctum`) | | Rate Limiting | ✅ | `leads`: 3/dk, `comments`: 3/dk (IP bazlı) | | Global API Throttle | ✅ | 60 istek/dk (`bootstrap/app.php`) | | Stateful API | ✅ | SPA oturumu için | | CORS | ✅ | `max_age: 86400` | | 404 Handler | ✅ | API isteklerinde JSON hata dönüşü | | SoftDeletes | ✅ | users, categories, courses, leads, comments | | Spatie Activity Log | ✅ | `spatie/laravel-activitylog` kurulu | ### 8.7. Swagger / OpenAPI Dökümantasyonu - **Paket:** `darkaonline/l5-swagger v10.1.0` - **Erişim:** `GET /api/documentation` - **Ana Annotation Dosyası:** `app/Http/Controllers/SwaggerAnnotations.php` - **Toplam Path:** 45+ endpoint, 77+ operasyon - Tüm controller'larda `@OA\Get`, `@OA\Post`, `@OA\Put`, `@OA\Delete` annotation'ları mevcuttur. ### 8.8. Teknik Altyapı | Paket | Versiyon | Kullanım | |-------|----------|----------| | PHP | 8.4 | Runtime | | Laravel Framework | v12 | Ana framework | | Laravel Sanctum | v4 | Token auth | | Spatie Permission | v7.2 | RBAC (48 permission, 2 rol) | | Spatie Activity Log | v4.12 | Audit log | | darkaonline/l5-swagger | v10.1 | API dökümantasyonu | | Pest | v4 | Test framework | | Laravel Pint | v1 | Kod formatlama | | Laravel Herd | - | Yerel sunucu | ### 8.9. Dosya Özeti | Kategori | Sayı | |----------|------| | Migration | 22 | | Model | 14 | | Enum | 8 | | Controller | 28 (+2 base/swagger) | | FormRequest | 25 | | API Resource | 13 | | Repository Interface | 13 | | Repository Eloquent | 13 | | Action | 34 | | DTO | 11 | | Policy | 11 | | Event | 1 | | Listener | 1 | | Seeder | 5 | | Factory | 13 | | **Toplam** | **~214 dosya** |