Flutter & Mobil İle Özelleştirilebilir E-Ticaret Sepet Modülü Nasıl Yapılır?

Flutter & Mobil İle Özelleştirilebilir E-Ticaret Sepet Modülü Nasıl Yapılır?
Flutter & Mobil İle Özelleştirilebilir E-Ticaret Sepet Modülü Nasıl Yapılır?

Gereksinimler ve Ön Hazırlık

Başarılı bir sepet modülü geliştirmek için Flutter SDK'nın en güncel sürümüne (3.24 ve üzeri önerilir) sahip olmanız gerekir. Durum yönetimi için Provider veya Riverpod gibi endüstri standardı kütüphaneleri kullanacağız. Bu örnekte, kodun okunabilirliği ve test edilebilirliği açısından Riverpod tercih edilmiştir.

  • Flutter SDK 3.24+
  • Riverpod (Durum yönetimi için)
  • Dart 3.5+
  • VS Code veya Android Studio IDE

Projenizin pubspec.yaml dosyasına flutter_riverpod ve hooks_riverpod paketlerini ekleyerek işe başlayın. Bu paketler, sepet verisinin uygulama genelinde tutarlı kalmasını sağlayacaktır.

Adım 1: Sepet Veri Modeli ve Ürün Yapısı

İlk adım, sepete eklenecek ürünlerin yapısını belirlemektir. Güvenli ve esnek bir yapı için CartItem sınıfını oluşturmalıyız. Bu sınıf, ürünün benzersiz kimliğini, adını, fiyatını ve miktarını içermelidir.

class CartItem {
  final String id;
  final String title;
  final double price;
  int quantity;

  CartItem({
    required this.id,
    required this.title,
    required this.price,
    this.quantity = 1,
  });

  // JSON verisi ile çalışırken kolaylık sağlar
  Map toJson() => {
    'id': id,
    'title': title,
    'price': price,
    'quantity': quantity,
  };
}

Bu model, veritabanı ile uygulama arasındaki köprüyü oluşturur. quantity değişkeninin değiştirilebilir olması, sepet içindeki miktar güncellemeleri için kritiktir.

Adım 2: Sepet Durum Yönetimi (State Management)

Sepet verilerini yönetmek için bir Notifier sınıfı oluşturmamız gerekiyor. Bu sınıf, ürün ekleme, çıkarma ve miktarı güncelleme gibi işlemleri yönetir. Riverpod'un Notifier yapısı, veriler değiştiğinde arayüzü otomatik olarak günceller.

import 'package:flutter_riverpod/flutter_riverpod.dart';

class CartNotifier extends Notifier {
  @override
  List build() => [];

  void addItem(CartItem item) {
    final index = state.indexWhere((i) => i.id == item.id);
    if (index != -1) {
      state[index].quantity++;
      state = [...state];
    } else {
      state = [...state, item];
    }
  }

  void removeItem(String id) {
    state = state.where((item) => item.id != id).toList();
  }
}

final cartProvider = NotifierProvider(CartNotifier.new);

Bu kod bloğunda, state değişkenini doğrudan değiştirmek yerine yeni bir liste oluşturuyoruz. Bu, Flutter'ın "immutable" (değişmez) veri yapısı prensibine uygundur ve performans hatalarını önler.

Adım 3: Özelleştirilebilir Sepet Arayüzü

Kullanıcının sepeti görüntüleyebileceği ve ürün miktarlarını değiştirebileceği bir arayüz tasarlayalım. Bu aşamada ListView.builder kullanarak dinamik bir liste oluşturacağız.

class CartScreen extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final cartItems = ref.watch(cartProvider);
    return Scaffold(
      appBar: AppBar(title: Text("Sepetim")),
      body: ListView.builder(
        itemCount: cartItems.length,
        itemBuilder: (context, index) {
          final item = cartItems[index];
          return ListTile(
            title: Text(item.title),
            subtitle: Text("${item.price} TL x ${item.quantity}"),
            trailing: IconButton(
              icon: Icon(Icons.delete),
              onPressed: () => ref.read(cartProvider.notifier).removeItem(item.id),
            ),
          );
        },
      ),
    );
  }
}

Burada ConsumerWidget kullanarak cartProvider verisini dinliyoruz. Veri her değiştiğinde build metodu tetiklenir ve arayüz güncellenir.

Adım 4: Sepet Hesaplamaları ve Toplam Tutar

E-ticaret uygulamalarında sepetteki toplam tutarı anlık olarak göstermek gerekir. Bunun için Provider kullanarak türetilmiş bir durum (derived state) oluşturabiliriz.

final totalAmountProvider = Provider((ref) {
  final cart = ref.watch(cartProvider);
  return cart.fold(0.0, (sum, item) => sum + (item.price * item.quantity));
});

Bu hesaplama yöntemi, sepet listesindeki her bir ürünün fiyatını ve miktarını çarparak toplam tutarı döner. fold fonksiyonu, listeyi tek bir değerde birleştirmek için en verimli yöntemdir.

Teknik Karşılaştırma: Sepet Yönetim Yaklaşımları

Yöntem Avantaj Dezavantaj
Riverpod (Notifier) Yüksek performans, test edilebilir Öğrenme eğrisi
Bloc Karmaşık iş mantığı için ideal Kod kalabalığı (boilerplate)
setState Basit, hızlı kurulum Büyük projelerde yönetilemez

Adım 5: Güvenlik ve Hata Yönetimi

Sepet modülünde en sık yapılan hata, kullanıcı miktar girişlerini doğrulamamaktır. Negatif miktar girilmesini engellemek için bir doğrulama katmanı eklemelisiniz.

Kritik Uyarı: Kullanıcıdan gelen verileri asla doğrudan veritabanına göndermeyin. Sepet tutarlarını her zaman sunucu tarafında (backend) tekrar doğrulayın. Mobil uygulama üzerindeki hesaplamalar sadece görsel amaçlıdır; asıl ödeme tutarı sunucu tarafından hesaplanmalıdır.

void updateQuantity(String id, int newQuantity) {
  if (newQuantity < 1) return; // Negatif veya sıfır miktar engellendi
  // Güncelleme mantığı...
}

Sıkça Sorulan Sorular

Sepet verilerini uygulamayı kapattıktan sonra nasıl saklarım?

Yerel depolama için shared_preferences veya daha karmaşık veriler için isar veya sqflite gibi yerel veritabanı çözümlerini kullanabilirsiniz.

Sepet senkronizasyonu nasıl yapılır?

Kullanıcı giriş yaptığında sepet verilerini bir API üzerinden sunucuya gönderip, uygulama açılışında bu verileri çekerek senkronizasyonu sağlayabilirsiniz.

Performans sorunlarını nasıl önlerim?

Çok fazla ürün içeren sepetlerde ListView yerine ListView.builder kullanarak sadece ekranda görünen öğelerin render edilmesini sağlayın.

Sepet modülünde animasyon nasıl eklenir?

AnimatedList widget'ını kullanarak ürün ekleme ve silme işlemlerine yumuşak geçişler ekleyebilirsiniz.

Sepet modülü test edilebilir mi?

Evet, Riverpod ve Flutter'ın widget_test kütüphaneleri ile sepetin tüm durumlarını birim testleri ile doğrulayabilirsiniz.

İleri Seviye Sepet Optimizasyonu: Isar ile Yerel Veri Kalıcılığı

Uygulama kapatıldığında sepet verilerinin kaybolmaması, kullanıcı deneyimi (UX) açısından kritik bir öneme sahiptir. Isar NoSQL veritabanı, Flutter uygulamalarında yüksek performanslı ve asenkron veri saklama imkanı sunar. Aşağıdaki örnekte, sepet öğelerini yerel cihazda nasıl kalıcı hale getirebileceğinizi görebilirsiniz.

Isar Veri Şeması Tanımlama

Öncelikle, sepet öğelerinizi temsil eden model sınıfını Isar'a uygun hale getirmelisiniz. Bu işlem, verilerin disk üzerinde hızlıca sorgulanmasını ve yazılmasını sağlar.

import 'package:isar/isar.dart';

part 'cart_item.g.dart';

@collection
class CartItem {
  Id id = Isar.autoIncrement;

  @Index()
  late String productId;
  late String name;
  late double price;
  late int quantity;
}

Sepet Verilerini Isar ile Kaydetme ve Okuma

Veritabanı işlemleri için bir servis katmanı oluşturmak, iş mantığını arayüzden ayırmanıza yardımcı olur. Aşağıdaki kod bloğu, sepete ürün ekleme ve mevcut sepeti getirme işlemlerini yönetir.

class CartDatabase {
  final Isar isar;

  CartDatabase(this.isar);

  Future addToCart(CartItem item) async {
    await isar.writeTxn(() async {
      await isar.cartItems.put(item);
    });
  }

  Future getAllItems() async {
    return await isar.cartItems.where().findAll();
  }
}

Sepet Modülünde Hata Ayıklama ve İzleme (Monitoring)

E-ticaret uygulamalarında sepet, en çok "race condition" (yarış durumu) hatasının yaşandığı bölümdür. Aynı anda birden fazla ürün ekleme veya silme işlemleri yapıldığında durum (state) tutarsızlıkları oluşabilir. Bu tür hataları minimize etmek için aşağıdaki stratejileri izleyebilirsiniz:

  • İşlem Kuyruğu (Transaction Queue): Sepet güncellemelerini eşzamanlı değil, sıralı bir kuyruk yapısıyla işleyin.
  • State Consistency Check: Sepet toplam tutarı ile ürünlerin birim fiyatlarının çarpımını periyodik olarak arka planda doğrulayın.
  • Logging: Kullanıcının sepete eklediği her ürünü ve gerçekleşen hataları Firebase Crashlytics veya benzeri bir araçla izleyin.

Kritik Hata Yönetimi Senaryosu

Aşağıdaki kod parçası, sepet güncelleme sırasında oluşabilecek hataları yakalamak için kullanılan güvenli bir güncelleme metodunu örneklendirir:

Future safeUpdateQuantity(String productId, int newQuantity) async {
  try {
    if (newQuantity < 0) throw Exception("Negatif miktar hatası");
    
    // Güncelleme mantığı burada çalışır
    await repository.update(productId, newQuantity);
  } catch (e) {
    // Hata durumunda kullanıcıya bildirim gönder
    debugPrint("Sepet güncellenirken hata oluştu: $e");
    rethrow; 
  }
}

Bu yaklaşımlar, uygulamanızın üretim ortamında (production) daha kararlı çalışmasını sağlar. Özellikle ödeme aşamasına geçmeden önce sepetin doğruluğunu teyit etmek, müşteri memnuniyetini doğrudan etkileyen bir faktördür.

Sonuç

Flutter ile özelleştirilebilir bir e-ticaret sepet modülü oluşturmak, doğru mimariyi seçmekle başlar. Riverpod gibi modern kütüphaneler kullanarak temiz, ölçeklenebilir ve yönetilebilir bir kod yapısı kurabilirsiniz. Bu rehberde öğrendiğiniz temel yapıları, kendi projelerinizde indirim kuponları, kargo hesaplamaları veya ürün varyasyonları gibi özelliklerle genişletebilirsiniz.

Yasal Sorumluluk Reddi: Bu makaledeki kod örnekleri eğitim amaçlıdır. Ticari bir uygulamada kullanmadan önce güvenlik açıklarına karşı (XSS, veri sızıntısı vb.) profesyonel güvenlik testlerinden geçirilmesi ve backend tarafında sunucu doğrulama mekanizmalarının kurulması zorunludur.

Bir sonraki adım olarak, sepet verilerini yerel bir veritabanına (Isar gibi) kaydetmeyi öğrenerek, kullanıcının uygulamayı kapatsa bile sepetinin korunmasını sağlayan bir yapı kurmayı deneyebilirsiniz.

Bu yazıya tepkinizi paylaşın:
Selin Yılmaz

Sürdürülebilir yaşam ve pratik ev yönetimi üzerine içerik stratejileri geliştiriyorum. Yalın anlatımı ve uygulanabilirliği ön planda tutan bir yazı dilim var.

Yorumlar (0)

Yorum Yaz