📊 Checkout Adres Sistemi - Kapsamlı Plan v3

📅 Tarih: 2025-12-02 | 🎯 Tenant: ixtif.com | 👤 Kapsam: Adres sistemi + Radio pattern + Subscription senaryosu + Product Type Fix

🔴 KRİTİK BULGU - v3'te Eklendi!

ShopProduct modeli requiresShipping() metoduna sahip DEĞİL!

Mevcut durum:

Bu düzeltilmeden subscription senaryosu tam çalışmaz!

🎯 Mevcut Sorunlar

1. Radio Button Pattern Eksikliği

Sorun: Kullanıcı birden fazla fatura adresi oluşturduğunda, aynı anda birden fazla adres seçili görünüyor.

Beklenen: Görsel olarak checkbox gibi görünmeli ama işlev olarak radio button gibi çalışmalı (tek seçim).

Teknik Sebep: Alpine.js :class binding doğru ama Livewire refresh sonrası state senkronizasyonu bozulabiliyor.

2. Form Bağımsızlığı Sorunu

Sorun: Fatura adresi formu açıkken teslimat adresi düzenlenemiyor veya seçilemiyor.

Beklenen: İki form tamamen bağımsız çalışmalı, birisi açıkken diğeri etkilenmemeli.

Teknik Sebep: State değişkenleri birbirini etkileyebiliyor.

3. Subscription Senaryosu KRİTİK

Gereksinim: Eğer sepette sadece subscription ürünü varsa, teslimat adresi bölümü gizlenmeli, sadece fatura adresi gösterilmeli.

4 Farklı Senaryo:

  • Scenario 1: Sadece Subscription → Teslimat gizli, fatura görünür
  • Scenario 2: Sadece Shop (physical) → Her ikisi de görünür
  • Scenario 3: Karışık (shop + subscription) → Her ikisi de görünür
  • Scenario 4 (YENİ!): Sadece Dijital Shop Ürünü → Teslimat gizli, fatura görünür

4. Product Type Sistemi Eksik YENİ - KRİTİK!

Sorun: ShopProduct'ta requiresShipping() metodu yok!

Mevcut Durum:

// CartItem.php - Mevcut (YANLIŞ) kontrol:
if ($this->product && property_exists($this->product, 'is_digital')) {
    return !$this->product->is_digital;
}

// ❌ ShopProduct'ta 'is_digital' field YOK!
// ✅ ShopProduct'ta 'product_type' enum var!

Gerekli Düzeltme: ShopProduct'a requiresShipping() metodu eklenip product_type kontrolü yapılmalı.

🏗️ 4 Senaryo - Mockup

Scenario 1: Sadece Subscription

📋 Fatura Bilgileri ✓ Görünür
📦 Teslimat Adresi
🔄 Toggle (Fatura = Teslimat)

Dijital ürün, kargo gereksiz.

Scenario 2: Sadece Shop (Physical)

📋 Fatura Bilgileri ✓ Görünür
📦 Teslimat Adresi ✓ Görünür
🔄 Toggle (Fatura = Teslimat) ✓ Görünür

Fiziksel ürün, kargo gerekli.

Scenario 3: Karışık (Shop + Subscription)

📋 Fatura Bilgileri ✓ Görünür
📦 Teslimat Adresi ✓ Görünür
🔄 Toggle (Fatura = Teslimat) ✓ Görünür

En az bir fiziksel ürün varsa kargo gerekli.

Scenario 4: Dijital Shop Ürünü (YENİ!)

📋 Fatura Bilgileri ✓ Görünür
📦 Teslimat Adresi
🔄 Toggle (Fatura = Teslimat)

Shop ürünü ama dijital (e-kitap, yazılım vb), kargo gereksiz.

✅ Çözüm Yaklaşımı

Adım 0: ShopProduct requiresShipping() Ekleme EN KRİTİK!

Dosya: Modules/Shop/app/Models/ShopProduct.php

Metod:

public function requiresShipping(): bool
{
    // Sadece PHYSICAL ürünler kargo gerektirir
    return $this->product_type === ProductType::PHYSICAL->value;
}

Açıklama: ProductType enum'ı kullanarak fiziksel ürün kontrolü yapar. DIGITAL, SERVICE, MEMBERSHIP, BUNDLE kargo gerektirmez.

Neden Kritik: Bu olmadan dijital shop ürünleri teslimat adresi isteyecek!

Adım 1: Alpine.js State Bağımsızlığı

Mevcut Durum: State değişkenleri birbirini etkileyebiliyor.

Çözüm: Her form için bağımsız state değişkenleri:

  • showShippingForm - Sadece teslimat formu kontrolü
  • showNewShippingForm - Teslimat yeni adres formu
  • showBillingAddressForm - Sadece fatura adresi bölümü
  • showNewBillingForm - Fatura yeni adres formu

Anahtar Nokta: Bir formdaki işlem diğer formun state'ini DEĞİŞTİRMEMELİ.

Adım 2: Radio Button Pattern

Görsel: Checkbox görünümü (yuvarlak, checkmark)

İşlev: Radio button mantığı (tek seçim)

Implementasyon:

  • Alpine.js :class binding ile dinamik CSS
  • Seçili adres: border-green-500 bg-green-900/10
  • Seçili olmayan: border-gray-700
  • Livewire refresh sonrası state senkronizasyonu korunmalı

Adım 3: Subscription Senaryosu Koşullu Render

Backend: $requiresShipping değişkeni zaten var (CheckoutPage.php)

Frontend: Blade koşullu renderlama

@if($requiresShipping)
    {{-- Teslimat Adresi Bölümü --}}
@endif

Toggle Görünürlük: Toggle butonu da aynı koşulla gizlenmeli.

Alpine.js State: requiresShipping değişkeni frontend'e aktarılmalı.

📋 Implementasyon Adımları

  1. ShopProduct requiresShipping() ekle KRİTİK
    • Modules/Shop/app/Models/ShopProduct.php'yi aç
    • requiresShipping() metodunu ekle
    • ProductType::PHYSICAL kontrolü yap
    • Test: Dijital ürün ekle, sepette requiresShipping false dönmeli
  2. Alpine.js state yapısını gözden geçir
    • checkout-page.blade.php x-data bölümü
    • State değişkenlerinin birbirinden bağımsız olduğunu doğrula
    • Çakışma varsa düzelt
  3. Teslimat adresi radio pattern uygula
    • @foreach döngüsünde her adres için :class binding
    • shippingAddressId ile karşılaştırma
    • Test: İki adres ekle, sadece biri seçili görünmeli
  4. Fatura adresi radio pattern uygula
    • Aynı mantık, billingAddressId ile
    • Test: İki fatura adresi, sadece biri seçili
  5. Form bağımsızlığını test et
    • Fatura formu aç → Teslimat seçimi yapılabilmeli
    • Teslimat formu aç → Fatura seçimi yapılabilmeli
    • İki form aynı anda açık → İkisi de çalışmalı
  6. Subscription senaryosu koşullu render
    • @if($requiresShipping) kontrolünü ekle
    • Toggle butonu da koşullu yap
    • Test: 4 senaryonun hepsini kontrol et
  7. Cache temizle ve production test
    • php artisan view:clear
    • php artisan responsecache:clear
    • Tüm senaryoları canlı ortamda test et

🧪 Test Senaryoları (4 Senaryo + Özellik Testleri)

Test 1: Sadece Subscription

Sepete sadece subscription ürünü ekle → Teslimat gizli, fatura görünür mü?

Test 2: Sadece Shop (Physical)

Sepete fiziksel shop ürünü ekle → Her iki adres de görünür mü? Toggle çalışıyor mu?

Test 3: Karışık (Shop + Subscription)

Sepete hem shop hem subscription ekle → Her ikisi de görünür mü?

Test 4: Dijital Shop Ürünü YENİ!

Sepete dijital shop ürünü ekle (product_type = 'digital') → Teslimat gizli, fatura görünür mü?

Test 5: Radio Selection

İki teslimat adresi ekle, birini seç → Sadece o seçili görünür mü? Diğerini seç → Önceki kalkıp yeni mi seçilir?

Test 6: Form Independence

Fatura formu açık → Teslimat adresini değiştir/seç → Çalışıyor mu? Fatura formu kapanmıyor mu?

📊 Beklenen Sonuçlar