# FikoYT Finans - Services & Directives

This directory contains Angular 20 services and directives for the FikoYT Finance application.

## Services

### 1. KutlamaService (Celebration Service)
**File:** `servisler/kutlama.service.ts`

Provides canvas-confetti animations for various financial achievements.

**Usage:**
```typescript
import { Component, inject } from '@angular/core';
import { KutlamaService } from './finans/servisler';

@Component({
  selector: 'app-dashboard',
  standalone: true,
  template: `
    <button (click)="kutla()">Kutla!</button>
  `
})
export class DashboardComponent {
  private kutlama = inject(KutlamaService);

  kutla() {
    this.kutlama.tasarrufBasarisi(); // Green confetti burst
    // or
    this.kutlama.borcOdendi(); // Multi-color rain
    // or
    this.kutlama.butceBasarisi(); // Gold sparkles
    // or
    this.kutlama.ilkKayit(); // Small celebration
    // or
    this.kutlama.netDegerRekor(); // Full screen fireworks
  }
}
```

**Methods:**
- `tasarrufBasarisi()` - Green confetti for savings goal
- `borcOdendi()` - Multi-color rain for debt payment
- `butceBasarisi()` - Gold sparkles for budget achievement
- `ilkKayit()` - Small celebration for first record
- `netDegerRekor()` - Full screen fireworks for net worth record

---

### 2. SesKomutService (Voice Command Service)
**File:** `servisler/ses-komut.service.ts`

Turkish voice command recognition using Web Speech API.

**Usage:**
```typescript
import { Component, inject, effect } from '@angular/core';
import { SesKomutService } from './finans/servisler';

@Component({
  selector: 'app-voice-input',
  standalone: true,
  template: `
    <button (click)="basla()" [disabled]="!servis.destekleniyor()">
      {{ servis.dinleniyor() ? 'Dinleniyor...' : 'Sesle Ekle' }}
    </button>
    <p>{{ servis.sonMetin() }}</p>
    @if (servis.hata()) {
      <p style="color: red;">{{ servis.hata() }}</p>
    }
  `
})
export class VoiceInputComponent {
  servis = inject(SesKomutService);

  constructor() {
    effect(() => {
      const metin = this.servis.sonMetin();
      if (metin) {
        const komut = this.servis.metniAyristir(metin);
        console.log('Komut:', komut);
        // Process command: {tip: 'kayit-ekle', tutar: 100, kategoriAd: 'market', kayitTipi: 'GIDER'}
      }
    });
  }

  basla() {
    this.servis.dinlemeyeBasla();
  }
}
```

**Example Commands:**
- "100 lira market harcaması ekle" → `{tip: 'kayit-ekle', tutar: 100, kategoriAd: 'market', kayitTipi: 'GIDER'}`
- "2500 lira maaş gelir ekle" → `{tip: 'kayit-ekle', tutar: 2500, kategoriAd: 'maaş', kayitTipi: 'GELIR'}`
- "bakiyem ne" → `{tip: 'sorgula', komut: 'bakiye-sorgula'}`
- "bu ayın harcaması" → `{tip: 'sorgula', komut: 'aylik-rapor'}`

**Signals:**
- `dinleniyor()` - Currently listening
- `sonMetin()` - Last recognized text
- `destekleniyor()` - Browser supports Speech Recognition
- `hata()` - Error message (null if no error)

---

### 3. DovizKuruService (Exchange Rate Service)
**File:** `servisler/doviz-kuru.service.ts`

Fetches and caches live exchange rates using open.er-api.com.

**Usage:**
```typescript
import { Component, inject, OnInit } from '@angular/core';
import { DovizKuruService } from './finans/servisler';

@Component({
  selector: 'app-currency',
  standalone: true,
  template: `
    <div>
      @if (servis.yukleniyor()) {
        <p>Kurlar yükleniyor...</p>
      }
      @for (doviz of servis.dovizKodlari(); track doviz) {
        <p>{{ doviz }}: {{ servis.kurGetir(doviz) | number:'1.2-2' }} ₺</p>
      }
    </div>
    <p>Son güncelleme: {{ servis.sonGuncelleme() | date:'short' }}</p>
  `
})
export class CurrencyComponent implements OnInit {
  servis = inject(DovizKuruService);

  ngOnInit() {
    // Auto-loads from cache or fetches fresh data
    // Manually refresh:
    this.servis.kurlariGuncelle();
  }

  cevirOrnek() {
    // Convert 100 USD to TRY
    const tryTutar = this.servis.donustur(100, 'USD', 'TRY');
    console.log('100 USD =', tryTutar, 'TRY');

    // Convert 1000 TRY to EUR
    const eurTutar = this.servis.donustur(1000, 'TRY', 'EUR');
    console.log('1000 TRY =', eurTutar, 'EUR');
  }
}
```

**Methods:**
- `kurlariGuncelle()` - Fetch latest rates (auto-cached for 5 minutes)
- `donustur(tutar, kaynak, hedef)` - Convert between currencies
- `kurGetir(dovizKodu)` - Get specific exchange rate
- `dovizKodlari()` - List available currency codes

**Signals:**
- `kurlar()` - Record<string, number> of exchange rates
- `sonGuncelleme()` - Last update timestamp
- `yukleniyor()` - Loading state
- `hata()` - Error message

**Supported Currencies:**
USD, EUR, GBP, CHF, JPY, CAD, AUD, SAR, KWD, AED, TRY

---

### 4. FisTaramaService (Receipt Scanner Service)
**File:** `servisler/fis-tarama.service.ts`

OCR receipt scanning using Tesseract.js with Turkish language support.

**Usage:**
```typescript
import { Component, inject } from '@angular/core';
import { FisTaramaService } from './finans/servisler';

@Component({
  selector: 'app-receipt-scanner',
  standalone: true,
  template: `
    <button (click)="kameradanTara()">Kameradan Tara</button>
    <input type="file" (change)="dosyadanTara($event)" accept="image/*">

    @if (servis.taraniyor()) {
      <p>Taranıyor... %{{ servis.ilerleme() }}</p>
    }

    @if (servis.sonuc(); as sonuc) {
      <div>
        <h3>Tarama Sonucu</h3>
        <p>Tutar: {{ sonuc.tutar | currency:'TRY' }}</p>
        <p>Tarih: {{ sonuc.tarih }}</p>
        <p>Mağaza: {{ sonuc.magazaAdi }}</p>
        <pre>{{ sonuc.metin }}</pre>
      </div>
    }

    @if (servis.hata()) {
      <p style="color: red;">{{ servis.hata() }}</p>
    }
  `
})
export class ReceiptScannerComponent {
  servis = inject(FisTaramaService);

  async kameradanTara() {
    try {
      const imageDataUrl = await this.servis.kameradanYakala();
      await this.servis.fisTara(imageDataUrl);
    } catch (error: any) {
      console.error('Kamera hatası:', error);
    }
  }

  async dosyadanTara(event: Event) {
    const input = event.target as HTMLInputElement;
    const file = input.files?.[0];
    if (!file) return;

    const reader = new FileReader();
    reader.onload = async (e) => {
      const imageDataUrl = e.target?.result as string;
      await this.servis.fisTara(imageDataUrl);
    };
    reader.readAsDataURL(file);
  }
}
```

**Methods:**
- `fisTara(imageDataUrl)` - Run OCR on image (base64 data URL)
- `kameradanYakala()` - Capture photo from camera
- `tutarCikar(metin)` - Extract amount from OCR text
- `tarihCikar(metin)` - Extract date from OCR text

**Signals:**
- `taraniyor()` - Scanning in progress
- `ilerleme()` - Progress (0-100)
- `sonuc()` - FisTaramaSonucu result object
- `hata()` - Error message

**FisTaramaSonucu Interface:**
```typescript
interface FisTaramaSonucu {
  metin: string;           // Full OCR text
  tutar: number | null;    // Extracted amount
  tarih: string | null;    // Extracted date (DD/MM/YYYY)
  magazaAdi: string | null; // Store name
}
```

---

## Directives

### AnimatedNumberDirective
**File:** `directives/animated-number.directive.ts`

Smoothly animates number changes with 60fps requestAnimationFrame.

**Usage:**
```typescript
import { Component } from '@angular/core';
import { AnimatedNumberDirective } from './finans/directives';

@Component({
  selector: 'app-balance',
  standalone: true,
  imports: [AnimatedNumberDirective],
  template: `
    <div>
      <h1
        [animatedNumber]="bakiye"
        [animatedDuration]="800"
        [animatedPrefix]="'₺'"
        [animatedDecimals]="2">
      </h1>
      <button (click)="artir()">Artır</button>
    </div>
  `
})
export class BalanceComponent {
  bakiye = 1000;

  artir() {
    this.bakiye += 250; // Number will animate smoothly
  }
}
```

**Inputs:**
- `animatedNumber` (number) - Target value (required)
- `animatedDuration` (number) - Animation duration in ms (default: 600)
- `animatedPrefix` (string) - Prefix like '₺' (default: '')
- `animatedSuffix` (string) - Suffix like '%' (default: '')
- `animatedDecimals` (number) - Decimal places (default: 0)

**Features:**
- Smooth 60fps animation using requestAnimationFrame
- Cubic ease-out easing function
- Turkish number formatting (thousands: '.', decimals: ',')
- Auto cleanup on destroy
- Zero allocations in animation loop

---

## Installation

**Required Dependencies:**
```bash
npm install canvas-confetti tesseract.js
```

**Types (if needed):**
```bash
npm install -D @types/canvas-confetti
```

---

## Browser Support

- **SesKomutService**: Requires Web Speech API (Chrome, Edge, Safari)
- **FisTaramaService**: Works in all modern browsers (Tesseract.js is pure JS)
- **DovizKuruService**: Requires fetch API (all modern browsers)
- **KutlamaService**: Requires canvas (all modern browsers)
- **AnimatedNumberDirective**: Requires requestAnimationFrame (all modern browsers)

---

## Notes

- All services use Angular Signals (no Observables)
- All services are standalone with `providedIn: 'root'`
- Services use `inject()` pattern internally
- TypeScript configured with `strict: false` for rapid development
- Exchange rates cached in localStorage for 5 minutes
- Voice commands support Turkish language only ('tr-TR')
- Receipt scanner uses Turkish OCR ('tur' language pack)

---

## File Structure

```
finans/
├── directives/
│   ├── animated-number.directive.ts
│   └── index.ts
├── servisler/
│   ├── kutlama.service.ts
│   ├── ses-komut.service.ts
│   ├── doviz-kuru.service.ts
│   ├── fis-tarama.service.ts
│   └── index.ts
└── README.md (this file)
```
