# 20. Hafta — Yeniden Kullanılabilir Widget

## Bu hafta ne yapacağız?

Aynı görünüme sahip öğrenci puan kartlarını kopyala-yapıştır kodla değil, parametre alan tek bir özel widget ile üreteceğiz. Karttan üst sayfaya olay bildirmek için callback kullanacağız. Özgün projede aynı yöntemi özet ve ders kartlarından oluşan başarı paneline uygulayacağız.

## Kazanımlar

- Tek sorumluluğu olan özel `StatelessWidget` oluşturma
- Görünümü kurucu parametreleriyle farklı veriler için kullanma
- `VoidCallback` ile alt widget'tan üst widget'a olay bildirme
- Veriyi üst bileşende, sunumu alt bileşende tutma
- Uzun widget ağacını okunabilir bileşenlere ayırma
- Aynı bileşenin farklı durumlarını test etme

## Çözümlü uygulama — Sınıf Puanları

### Model ve durumun sahibi

Puan değişebildiği için öğrenci modelleri `StatefulWidget` olan sayfada tutulur.

```dart
class OgrenciPuani {
  OgrenciPuani(this.ad, this.etkinlik, this.puan);
  final String ad;
  final String etkinlik;
  int puan;
}

void degistir(OgrenciPuani ogrenci, int fark) {
  setState(() {
    ogrenci.puan = (ogrenci.puan + fark).clamp(0, 100);
  });
}
```

### Parametreli kart

Kart veriyi değiştirmez. Görüntülemek için metin ve puan, olay bildirmek için iki callback alır.

```dart
class PuanKarti extends StatelessWidget {
  const PuanKarti({
    super.key,
    required this.ad,
    required this.etkinlik,
    required this.puan,
    required this.onAzalt,
    required this.onArtir,
  });

  final String ad;
  final String etkinlik;
  final int puan;
  final VoidCallback onAzalt;
  final VoidCallback onArtir;
}
```

Kartın içindeki düğme yalnız kendisine verilen işlevi çağırır:

```dart
IconButton(
  tooltip: '5 puan artır',
  onPressed: onArtir,
  icon: const Icon(Icons.add_circle_outline),
)
```

### Aynı widget'ı farklı verilerle kullanma

```dart
...puanlar.map((ogrenci) => PuanKarti(
  ad: ogrenci.ad,
  etkinlik: ogrenci.etkinlik,
  puan: ogrenci.puan,
  onAzalt: () => degistir(ogrenci, -5),
  onArtir: () => degistir(ogrenci, 5),
))
```

Bu yapı sayesinde kart tasarımındaki bir değişiklik bütün öğrencilere uygulanır. Testte Ece'nin artırma düğmesine basılmış ve puanı 85'ten 90'a yükselmiştir.

![Puan Kartı gerçek Flutter ekranı](../../screenshots/week-20-adapted.png)

## Özgün uygulama — Ders Başarı Panelim

Bu projede üç sorumluluk ayrı widget'lara bölünür:

- `BasariPaneli`: verileri ve filtre durumunu yönetir.
- `OzetKarti`: ortalama ve hedef sayısını sunar.
- `DersKarti`: tek dersin notunu, hedefini ve çalışma düğmesini sunar.

### Özet kartını kullanma

```dart
OzetKarti(
  ortalama: ortalama,
  hedefte: dersler.where((d) => d.not >= d.hedef).length,
  toplam: dersler.length,
)
```

### Ders kartına davranış verme

```dart
DersKarti(
  ders: ders,
  onCalismaEkle: () => setState(() {
    ders.not = (ders.not + 3).clamp(0, 100);
  }),
)
```

Filtre açıldığında yalnız notu hedefinin altında kalan dersler gösterilir. Ekrandaki ortalama, her değişiklikten sonra ana listedeki güncel notlardan yeniden hesaplanır.

![Ders Başarı Paneli gerçek Flutter ekranı](../../screenshots/week-20-original.png)

## Uygulama görevleri

### Kolay — Ürün etiketi

Ad, fiyat, stok durumu ve renk alan parametreli bir `UrunKarti` oluşturup en az dört ürün için kullanın.

### Orta — Yoklama kartı

Öğrenci adı, numarası ve yoklama durumu alan kart geliştirin. Karttaki düğme callback ile ana sayfadaki durumu değiştirsin.

### İleri — Proje değerlendirme paneli

Tasarım, kod kalitesi ve sunum puanlarını gösteren yeniden kullanılabilir ölçüt kartları oluşturun. Her kart puan değişimini üst bileşene bildirsin; toplam ve ortalama ayrı özet widget'ında güncellensin.

## Tasarım kontrolü

- Widget adı yaptığı işi açıkça anlatıyor mu?
- Alt widget, ihtiyacı olmayan tüm modeli almak yerine gerekli parametreleri mi alıyor?
- Değişebilir veri tek ve açık bir üst bileşende mi tutuluyor?
- Alt bileşen olayları callback ile mi bildiriyor?
- Tekrarlanan görünüm kodu gerçekten ortak widget'a taşındı mı?
- Düşük, orta ve yüksek puanlarda renk ve taşma kontrol edildi mi?

## Geri bildirim ve çözüm erişimi

Öğrenci kendi bileşenlerini gönderdikten sonra **İpucunu göster** yalnız bileşen sınırlarını ve callback yönünü açıklar. **Örnek çözümü göster** gerçek `lib/main.dart` kodunu; proje indirme bağlantısı ise bütün Flutter kaynaklarını çevrim dışı kullanım için sunar.

## Kaynak projeler

- Konu uygulaması: `05 - Modelleme ve Listeler/Uygulamalar/Uygulama-20-Puan Kartı`
- Özgün uygulama: `05 - Modelleme ve Listeler/Uygulamalar/Ozgun-20-Ders Başarı Paneli`
