# Faz 2: Gamification Uygulama Plani

**Tarih:** 2026-04-19
**Kapsam:** Streak sistemi, rozetler, istatistik kartlari, paylasim, bildirimler, kutlama animasyonu

---

## Adim 1: Isar Model Olusturma — GamificationData

**Dosya:** `lib/apps/mesaici/model/gamification/gamification_data.dart`
**Dosya:** `lib/apps/mesaici/model/gamification/gamification_data.g.dart` (auto-generated)

**Yapilacak:**
- `GamificationData` Isar `@collection` modeli olustur:
  - `Id id = 0` (singleton, tek kayit)
  - `int streak = 0` — mevcut ardisik gun sayisi
  - `int enUzunStreak = 0`
  - `DateTime? sonKayitTarihi` — son calisma kaydi girilen gun
  - `List<String> kazanilanRozetler` — rozet ID listesi
  - `List<DateTime> rozetTarihleri` — her rozet icin kazanilma tarihi (index eslesmeli)
  - `int toplamKayitGunu = 0` — toplam kayit girilen gun sayisi
  - `int erkenGirisSayisi = 0` — mesaiden once giris sayaci
  - `int geceCikisiSayisi = 0` — mesai sonrasi cikis sayaci
  - `int konumTakipGunu = 0` — otomatik konum takibi kullanan gun sayisi
- JSON serialization: `fromJson` / `toJson`

**Bagimlilık:** Yok (ilk adim)

---

## Adim 2: Rozet Tanim Modeli

**Dosya:** `lib/apps/mesaici/model/gamification/rozet.dart`

**Yapilacak:**
- `Rozet` sinifi (Isar `@embedded`):
  - `String id` — benzersiz rozet ID (orn: `ilk_adim`, `duzenli_calisan`, `maraton`)
  - `String ismi`
  - `String aciklama`
  - `String simge` — emoji veya asset yolu
  - `int hedef` — hedef sayi (orn: 7 gun, 30 gun)
  - `RozetKategori kategori` — enum: STREAK, GIRIS_CIKIS, FAZLA_MESAI, MAAS, KONUM
- `RozetTanimlari` static sinifi — tum rozetleri tanimlayan sabit liste:

| ID | Ismi | Kosul | Hedef |
|---|---|---|---|
| `ilk_adim` | Ilk Adim | Ilk mesai kaydi | 1 |
| `duzenli_calisan` | Duzenli Calisan | 7 gun streak | 7 |
| `mesai_ustasi` | Mesai Ustasi | 30 gun streak | 30 |
| `maratoncu` | Maratoncu | 90 gun streak | 90 |
| `efsane` | Efsane | 365 gun streak | 365 |
| `erken_kus` | Erken Kus | 10 kez erken giris | 10 |
| `gece_kusu` | Gece Kusu | 10 kez gec cikis | 10 |
| `fazla_mesai_krali` | Fazla Mesai Krali | Ayda 20+ saat fazla mesai | 20 |
| `tasarrufcu` | Tasarrufcu | 3 ay ust uste net maas artisi | 3 |
| `dakik` | Dakik | 30 gun ust uste tam saatinde giris | 30 |
| `konum_uzmani` | Konum Uzmani | Otomatik takibi 30 gun kullan | 30 |

**Bagimlilık:** Yok

---

## Adim 3: Isar Schema Kaydini Guncelle

**Dosya:** `lib/apps/mesaici/servisler/fikoyt.mesaici.service.dart`
**Dosya:** `lib/apps/mesaici/model/calisma_kayit/calisma_kayit.dart` (Isolate fonksiyonu icindeki Isar.open)
**Dosya:** `lib/apps/mesaici/model/model_hareketler.dart` (Isolate fonksiyonu icindeki Isar.open)
**Dosya:** `lib/apps/mesaici/servisler/mesaici.background/mesaici.background.dart` (arka plan servisindeki Isar.open)

**Yapilacak:**
- `Isar.open()` cagrılarına `GamificationDataSchema` ekle
- Tum Isolate fonksiyonlarindaki `Isar.open()` cagrilarini da guncelle
- `FikoYTMesaiciService.init()` icinde gamification verilerini yukle (Adim 5 ile birlikte)

**Bagimlilık:** Adim 1

---

## Adim 4: GamificationService Olusturma

**Dosya:** `lib/apps/mesaici/servisler/gamification.service.dart`

**Yapilacak:**
- `GamificationService` sinifi (`GetxService` extend):
  - `Rx<GamificationData> veri` — reaktif gamification verisi
  - `RxList<String> yeniRozetler` — son oturumda kazanilan rozetler (animasyon icin)

**Metotlar:**
1. `Future<void> init(Isar isar)` — Isar'dan GamificationData oku, yoksa olustur
2. `Future<void> kayitGuncelle(DateTime kayitTarihi)` — yeni calisma kaydi girildiginde cagrilir:
   - `sonKayitTarihi` ile mevcut tarihi karsilastir
   - Ayni gun ise islem yapma
   - Ardisik is gunu ise `streak++` (hafta tatili/izin gunlerini atla, bozmaz)
   - Ardisik degilse `streak = 1`
   - `enUzunStreak = max(streak, enUzunStreak)`
   - `toplamKayitGunu++`
   - `sonKayitTarihi = kayitTarihi`
   - Rozet kontrol cagir
3. `Future<void> girisKontrol(DateTime girisSaati, DateTime? mesaiBaslangic)` — erken giris kontrolu:
   - Giris saati mesai baslangicından once ise `erkenGirisSayisi++`
4. `Future<void> cikisKontrol(DateTime cikisSaati, DateTime? mesaiBitis)` — gec cikis kontrolu:
   - Cikis saati mesai bitisinden sonra ise `geceCikisiSayisi++`
5. `Future<List<String>> rozetKontrol()` — tum rozet kosullarini kontrol et, yeni kazanilanlari dondur:
   - Streak milestone'lar: streak >= 7/30/90/365
   - `ilk_adim`: toplamKayitGunu >= 1
   - `erken_kus`: erkenGirisSayisi >= 10
   - `gece_kusu`: geceCikisiSayisi >= 10
   - `fazla_mesai_krali`: bu ayin toplam fazla mesaisi >= 20 saat (Isar'dan hesapla)
   - `dakik`: ardisik dakik giris sayisi >= 30 (ayri alan gerekebilir — `ardisikDakikGiris` ekle)
   - Zaten kazanilmis rozeti tekrar ekleme
   - Yeni kazanilanlari `yeniRozetler`'e ekle (kutlama animasyonu icin)
6. `Future<void> kaydet()` — GamificationData'yi Isar'a yaz
7. `bool rozetKazanildiMi(String rozetId)` — rozet var mi kontrol
8. `DateTime? rozetTarihiAl(String rozetId)` — rozet kazanilma tarihi

**Streak Is Gunu Hesabi:**
- `Vardiya.gunAyarlari` uzerinden bugunun `GunTuru`'nu al
- `DINLENME_GUNU` ve `HAFTA_TATILI` gunleri streak'i bozmaz
- Sadece `CALISMA_GUNU` olup kayit girilmemis gunler streak'i kirar
- Resmi tatiller de streak'i bozmaz (`ModelAyarlar.resmiTatiller` listesinden kontrol)

**Bagimlilık:** Adim 1, 2, 3

---

## Adim 5: GamificationService'i FikoYTMesaiciService'e Entegre Et

**Dosya:** `lib/apps/mesaici/servisler/fikoyt.mesaici.service.dart`

**Yapilacak:**
- `FikoYTMesaiciService` icine:
  - `late GamificationService gamification` alani ekle
  - `init()` icinde `gamification = GamificationService()` ve `gamification.init(isar!)` cagir
  - `Get.put<GamificationService>(gamification)` ile DI'ya ekle

**Bagimlilık:** Adim 3, 4

---

## Adim 6: CalismaKayit Akisina Gamification Hook'u Ekle

**Dosya:** `lib/apps/mesaici/widgets/aktif_kart/giris_cikis_butonlari.dart`
**Dosya:** `lib/apps/mesaici/widgets/aktif_kart/aktif_kart.dart`
**Dosya:** `lib/apps/mesaici/servisler/fikoyt.mesaici.service.dart` (aktifCalisma listener)

**Yapilacak:**
- Kayit Isar'a yazildiktan sonra (aktifCalisma listener'daki `isar.writeTxn` callback'inde):
  - `gamification.kayitGuncelle(aktifCalisma.value.tarih)` cagir
- Giris butonu basildiginda:
  - `gamification.girisKontrol(giris, bugununAyari.girisSaati)` cagir
- Cikis butonu basildiginda:
  - `gamification.cikisKontrol(cikis, bugununAyari.cikisSaati)` cagir
- Background servis uzerinden otomatik kayit oldugunda da ayni hook'lar calissin:
  - `mesaici.background.dart` icindeki kayit kaydetme mantığına gamification update ekle
- Rozet kontrolu sonrasi `yeniRozetler` listesi dolu ise kutlama animasyonu tetikle (Adim 10)

**Bagimlilık:** Adim 4, 5

---

## Adim 7: Streak Widget — Ana Sayfa Karti

**Dosya:** `lib/apps/mesaici/widgets/streak_karti/streak_karti.dart`

**Yapilacak:**
- `StreakKarti` StatelessWidget:
  - `GamificationService`'den `veri` reactive olarak oku
  - Gosterim:
    - Ates emoji + streak sayisi: "15 gundur mesaini takip ediyorsun"
    - Ilerleme cubugu: bir sonraki milestone'a kalan gun (7 → 30 → 90 → 180 → 365)
    - En uzun streak bilgisi (kucuk yazi)
  - Animasyonlar:
    - Streak sayisi degistiginde scale + bounce animasyonu (`flutter_animate`)
    - Milestone'a ulasinca pariltili efekt (shimmer)
  - Tema uyumlu: dark/light mode (FikoTheme extension kullan)
  - Kart stili: mevcut `OzetAylik` kartıyla ayni gorunumde (Container + BoxDecoration)

**Dosya:** `lib/apps/mesaici/mesaici_home.dart`

**Yapilacak:**
- `body` listesine `AktifKart`'tan once `StreakKarti` widget'i ekle
- `Obx` ile sar (gamification veri degisimini dinle)

**Bagimlilık:** Adim 5

---

## Adim 8: Haftalik/Aylik Istatistik Kartlari

**Dosya:** `lib/apps/mesaici/widgets/istatistik_karti/haftalik_ozet_karti.dart`
**Dosya:** `lib/apps/mesaici/widgets/istatistik_karti/aylik_ozet_karti.dart`

**Yapilacak:**

### HaftalikOzetKarti:
- Bu haftanin toplam calisma suresi (Isar sorgusu: son 7 gundeki kayitlar)
- Gecen haftayla karsilastirma yuzdesi
- En uzun / en kisa gun
- Fazla mesai toplami

### AylikOzetKarti:
- Mevcut `OzetAylik` widget'i zaten aylik ozet veriyor — bunu genislet veya yanina ekle:
  - "Bu ay tahmini net maas: X TL"
  - "Fazla mesain: Y saat Z dakika"
  - Gecen ayla karsilastirma

**Dosya:** `lib/apps/mesaici/mesaici_home.dart`
- `body` listesine `OzetAylik`'tan sonra `HaftalikOzetKarti` ekle

**Bagimlilık:** Adim 5 (gamification verisine dogrudan bagli degil ama ayni servis altyapisi)

---

## Adim 9: Rozet/Basarim Gorunumu — Profil Kartinda

**Dosya:** `lib/apps/mesaici/widgets/rozet_vitrin/rozet_vitrin.dart`
**Dosya:** `lib/apps/mesaici/widgets/rozet_vitrin/rozet_item.dart`

**Yapilacak:**

### RozetVitrin Widget:
- Yatay scrollable rozet listesi (horizontal ListView)
- Kazanilmis rozetler renkli + tarih bilgisiyle
- Kazanilmamis rozetler gri/kilitli + ilerleme gostergesiyle
- Her rozet icin `RozetItem` widget:
  - Yuvarlak ikon (emoji veya asset)
  - Rozet ismi (altta)
  - Kazanildiysa tarih, kazanilmadiysa ilerleme ("7/30 gun")
  - Tiklayinca detay bottom sheet (aciklama + kosul + kazanilma tarihi)

### Profil Kartina Entegrasyon:
**Dosya:** `lib/apps/mesaici/widgets/kullanici_bilgi_navigasyon/kullanici_bilgi_navigasyon.dart`
- Profil kartinin altina `RozetVitrin` ekle
- Veya `mesaici_home.dart`'ta profil alaninin hemen altinda ayri section olarak ekle

**Bagimlilık:** Adim 4, 5

---

## Adim 10: Rozet Kazanma Kutlama Animasyonu

**Dosya:** `lib/apps/mesaici/widgets/rozet_kutlama/rozet_kutlama_dialog.dart`

**Yapilacak:**
- `RozetKutlamaDialog` — tam ekran overlay animasyonu:
  - Konfeti efekti (CustomPainter veya `flutter_animate` ile)
  - Rozet ikonu buyuyerek ortada belirir (scale 0→1 + bounce)
  - "Tebrikler! 'Duzenli Calisan' rozetini kazandin!" yazisi fade-in
  - Alt kismda ilerleme bilgisi: "Siradaki hedef: 30 gun streak"
  - 3 saniye sonra veya tiklayinca kapanir
- Tetikleme mekanizmasi:
  - `GamificationService.yeniRozetler` dinle
  - Liste bos degilse `showDialog` ile `RozetKutlamaDialog` goster
  - Gosterdikten sonra `yeniRozetler.clear()`

**Dosya:** `lib/apps/mesaici/mesaici_home.dart`
- `initState` icinde veya `build` icinde `ever(gamification.yeniRozetler, ...)` listener ekle

**Bagimlilık:** Adim 6 (rozetlerin tetiklenmesi gerekiyor)

---

## Adim 11: Paylasılabilir Rapor Karti Olusturma

**Dosya:** `lib/apps/mesaici/servisler/rapor_karti.service.dart`
**Dosya:** `lib/apps/mesaici/widgets/rapor_karti/rapor_karti_gorsel.dart`

**Yapilacak:**

### RaporKartiService:
- `Future<File> aylikRaporKartiOlustur(DateTime ay)` metodu:
  - `RepaintBoundary` + `RenderRepaintBoundary.toImage()` ile widget'i gorsele cevir
  - 1080x1920 boyutunda (Instagram story formati)
  - `share_plus` paketi ile paylasim

### RaporKartiGorsel Widget:
- 1080x1920 boyutunda gorunmez widget (RepaintBoundary icinde):
  - Ust kisim: FikoYT logosu + kullanici adi + sirket
  - Orta kisim:
    - Ay ismi + yil
    - Net maas (buyuk font)
    - Toplam calisma saati
    - Fazla mesai suresi
    - Streak bilgisi
    - Kazanilan rozet ikonlari (son ayda kazanilanlar)
  - Alt kisim: "FikoYT Mesaici ile olusturuldu" watermark
  - Gradient arka plan (tema renklerine uyumlu)

### pubspec.yaml Degisikligi:
**Dosya:** `pubspec.yaml`
- `share_plus: any` ekle (dependencies altina)

**Bagimlilık:** Adim 5, 8

---

## Adim 12: Bildirim Stratejisi Uygulamasi

**Dosya:** `lib/apps/mesaici/servisler/mesaici.background/mesaici.background.dart`
**Dosya:** `lib/apps/mesaici/model/ayarlar/model_ayarlar.dart` (BildirimAyarlari genisletmesi)

**Yapilacak:**

### BildirimAyarlari Genisletmesi:
- `BildirimAyarlari` embedded modeline yeni alanlar ekle:
  - `bool streakHatirlatmasi = true`
  - `bool haftalikOzet = true`
  - `bool aylikRapor = true`

### Background Servis Timer Guncellemesi:
Mevcut `mesaici.background.dart`'taki periyodik timer'a su kontrolleri ekle:

1. **Streak Hatirlatmasi (aksam 21:00):**
   - Saat 21:00 civari ve bugun kayit yoksa:
   - "Streak'in kopmasin! Bugun kayit yok" bildirimi gonder
   - Bildirim ID: sabit (orn: 5001)

2. **Gunluk Ozet (aksam 20:00):**
   - Saat 20:00 civari ve bugun kayit varsa:
   - "Bugun Xs Ydk calistin, brut kazancin ~Z TL" bildirimi

3. **Haftalik Ozet (Pazar 18:00):**
   - Gun = Pazar ve saat 18:00 civari:
   - Haftalik toplam calisma, streak durumu bildirimi

4. **Aylik Rapor (ay sonu):**
   - Ayin son gunu ve saat 20:00 civari:
   - "Aylik raporun hazir! Goruntule" bildirimi
   - Bildirime tiklaninca rapor karti sayfasina yonlendir

### Bildirim Kanallari:
- Mevcut `bildirim()` ve `sartliBildirim()` fonksiyonlarini kullan
- Yeni kanal isimleri: `"StreakHatirlatma"`, `"GunlukOzet"`, `"HaftalikOzet"`, `"AylikRapor"`

**Bagimlilık:** Adim 4, 5, 6

---

## Adim 13: Ayarlar Sayfasina Gamification Secenekleri Ekle

**Dosya:** `lib/apps/mesaici/pages/ayarlar/uygulama_ayarlari.dart`

**Yapilacak:**
- Bildirim ayarlari bolumune yeni switch'ler ekle:
  - "Streak hatirlatmasi" toggle
  - "Haftalik ozet bildirimi" toggle
  - "Aylik rapor bildirimi" toggle
- Gamification verilerini sifirla butonu (onay dialogu ile)

**Bagimlilık:** Adim 12

---

## Uygulama Sirasi (Onerilen)

```
Adim 1  ─── Model: GamificationData
Adim 2  ─── Model: Rozet tanimlari
   │
Adim 3  ─── Isar schema kaydi
   │
Adim 4  ─── GamificationService
Adim 5  ─── Servis entegrasyonu
   │
   ├── Adim 6  ─── CalismaKayit hook'lari
   ├── Adim 7  ─── Streak widget (ana sayfa)
   ├── Adim 8  ─── Istatistik kartlari
   └── Adim 9  ─── Rozet vitrini
         │
         Adim 10 ─── Kutlama animasyonu
         Adim 11 ─── Paylasim rapor karti
         Adim 12 ─── Bildirim stratejisi
         Adim 13 ─── Ayarlar sayfasi
```

**Paralel calismalar:** Adim 6, 7, 8, 9 birbirinden bagimsiz, ayni anda gelistirilebilir.

---

## Teknik Notlar

### Mevcut Yapiyla Uyum
- Tum widget'lar `FikoTheme` extension'i kullanacak (dark/light uyum)
- State yonetimi: GetX (`Rx`, `Obx`) — mevcut pattern ile ayni
- Isar versiyon: 3.1.0+1 (mevcut — migration gerekebilir)
- Animasyonlar: `flutter_animate` paketi zaten mevcut

### Yeni Paket Gereksinimleri
- `share_plus: any` — rapor karti paylasimi (Adim 11)
- Baska yeni paket gerekmiyor

### Isar Migration
- Yeni `GamificationData` collection eklenmesi Isar'da otomatik migration ile calisir (yeni collection, mevcut veri bozulmaz)
- `BildirimAyarlari`'na yeni `bool` alanlar eklemek de sorunsuz (varsayilan deger atanir)

### Performans
- `GamificationService` singleton, bir kez yuklenir
- Rozet kontrolu sadece yeni kayit girildiginde calisir (her frame degil)
- Streak hesabi O(1) — sadece `sonKayitTarihi` karsilastirmasi
- Haftalik/aylik istatistik sorgulari Isar index'leri uzerinden calisir (tarih aralik sorgusu)
